I’ve been doing the Weekly
Challenges. The
latest
involved ordinal numbers and Unicode generation. (Note that this is
open until 28 August 2022.)
Task 1: Ordinal Number Spelling
You are given a positive number, $n
.
Write a script to spell the ordinal number.
While it's trivial for the two-digit examples given, doing this
properly is quite hard work, and I didn't feel like putting in that
effort across multiple languages. And doing it in Perl and Raku is a
solved problem, thanks to Lingua::EN::Numbers
(a different module
with a slightly different interface in each language). So I used that,
and abandoned the others. If I had to do this elsewhere, I'd
probably port the Perl code – or of course look up the Rosetta
Code page.
Raku:
use Lingua::EN::Numbers;
is(ordinal(11),"eleventh",'example 1');
and in Perl similarly
use Lingua::EN::Numbers qw(num2en_ordinal);
is(num2en_ordinal(11),"eleventh",'example 1');
Task 2: Unicode Sparkline
You are given a list of positive numbers, @n
.
Write a script to print sparkline in Unicode for the given list of
numbers.
A "sparkline" is apparently a low-resolution graph that's built up
from line-drawing characters. In Unicode, we have U+2581 LOWER ONE EIGHTH BLOCK
to U+2588 FULL BLOCK
.
PostScript, of course, doesn't support UTF-8 at all… but in a UTF-8
console, it can be made to emit the right multibyte sequences,
UTF-8-encoded in advance. (As with all the languages, I build up bar
as an array of bar characters, then concatenate the right ones out of
that array.)
/sparkline {
9 dict begin
/nn exch def
/bar 8 array def
0 1 7 {
/i exch def
/cc 3 string def
cc 0 16#e2 put
cc 1 16#96 put
cc 2 16#81 i add put
bar i cc put
} for
/mn nn listmin def
/mx nn listmax def
/inscale mx mn sub def
/outscale bar length def
/out nn length 3 mul string def
0 1 nn length 1 sub {
/i exch def
out i 3 mul
bar nn i get mn sub inscale div outscale mul cvi outscale 1 sub min get
putinterval
} for
out
end
} bind def
In JavaScript, String.fromCharCode()
only works for UCS-2 (i.e. the
16-bit Basic Multilingual Plane), but the characters used here are in
that span so I can get away with it.
function sparkline(nn) {
let bar = [];
for (let bc = 9601; bc <= 9608; bc++) {
bar.push(String.fromCharCode(bc));
}
let mn = Math.min(...nn);
let mx = Math.max(...nn);
let inscale = mx - mn;
let outscale = bar.length;
let out = "";
for (let v of nn) {
let va = Math.min(Math.floor((v - mn) / inscale * outscale),
outscale - 1);
out += bar[va];
}
return out;
}
Same in Kotlin, which similarly has 16-bit Char
types. But most
of these languages don't have a problem with Unicode and UTF-8 now, at
least as long as nobody's asking them actually to understand it (e.g.
to split a string into characters).
Full code on
github.
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.