Echo and wordy numbers
Weekly challenge 362 — 23 February 2026
Week 362: 23 Feb 2026
You are given an array of integers. Write a script to return them in alphabetical order, in any language of your choosing.
Example 1 Input: (6, 7, 8, 9 ,10) Output: (8, 9, 7, 6, 10) eight, nine, seven, six, ten Example 2 Input: (-3, 0, 1000, 99) Output: (-3, 99, 1000, 0) minus three, ninety-nine, one thousand, zero Example 3 Input: (1, 2, 3, 4, 5) Output: (5, 2, 4, 3, 1) for French language cinq, deux, quatre, trois, un Output: (5, 4, 1, 3, 2) for English language five, four, one, three, two Example 4 Input: (0, -1, -2, -3, -4) Output: (-4, -1, -3, -2, 0) minus four, minus one, minus three, minus two, zero Example 5 Input: (100, 101, 102) Output: (100, 101, 102) one hundred, one hundred and one, one hundred and two
I submitted this challenge without thinking too hard about how easy it would be. The answer seems to be that it can be pretty easy or quite tricky, depending on your approach.
The tricky part is converting a number to its English language representation. The easy way to do that is to use a CPAN module, of which there are several candidates, and I chose one which provides a very concise interface:
use Lingua::EN::Numbers::Easy;
$words = $N{$number};
Its only slight drawback is that it returns, for example,
-3 as negative 3. Also, it sometimes enters a comma where
one isn't normally used.
That's my 'Output 1' solution.
The harder way to do it is avoid modules and code it all in Perl, which has to cope with a number of idiosyncracies in the English language and in the way numbers are expressed in English. In fact not all variants of English agree on this, so I have used the wording generally used in a formal context in the UK. That's my 'Output 2' solution.
Converting to words is not the end of the solution, however. In both cases I created an array where the elements are
$words . ' ' . $number
for example, twelve 12.
That sorts in the correct order, and it's only then
necessary to extract the trailing numbers (and minus sign) to create the
desired output.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2026-02-23 use utf8; # Week 362 - task 2 - Spellbound sorting use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; use Lingua::EN::Numbers::Easy; spellbound_sorting(6, 7, 8, 9, 10); spellbound_sorting(-3, 0, 1000, 99); spellbound_sorting(1, -2, 3, -4, 5); spellbound_sorting(100, 1000, 1000000, 1000000000); spellbound_sorting(0, 5, 0, 5); spellbound_sorting(123, 10**12, -999); spellbound_sorting(9, 99, 999, 9999); spellbound_sorting(100123006); sub spellbound_sorting { my (@input, @output, @words, $w, $method, $explain); # initialise @input = @_; # try two methods for $method (1 .. 2) { @output = (); $explain= ''; # make array of eg 'twenty-one¦21' if ($method == 1) { $words[$_] = number_to_words1($input[$_]) . qq[ $input[$_]] for 0 .. $#input; } else { $words[$_] = number_to_words2($input[$_]) . qq[ $input[$_]] for 0 .. $#input; } # sort it into alphabetical order @words = sort { $a cmp $b } @words; # extract numbers for $w (@words) { $w =~ m|(.*?) (-?\d+)|; push(@output, $2); $explain .= qq[$1; ]; } # report say qq[\nInput: (] . join(', ', @input) . ')' unless $method == 2; say qq[Output $method: (] . join(', ', @output) . ')'; say qq[ ] . substr($explain, 0, -2); } } sub number_to_words1 { # using Lingua::EN::Numbers::Easy my $words = $N{$_[0]}; $words =~ s|negative|minus|; return $words; } sub number_to_words2 { # using Perl my ($number, $digits, $words, $j, $piece, $minus, @chunks, $three); @chunks = ('billion', 'million', 'thousand', ''); # check for -ve number $number = shift; $minus = $number < 0; $number = -$number if $minus; # check for special cases return 'invalid' if ($number =~ m|[^\d]| or $number > 10**12); return 'zero' if $number == 0; return 'one trillion' if $number == 10**12; # make number into words 3 digits at a time $words = ''; $digits = sprintf('%012d', $number); while ($digits =~ m|(\d\d\d)|g) { if ($1) { # ie not 000 $three = three_digits($1); $words .= ' and ' if ($words and $chunks[0] eq '' and $1 =~ m|^0| and $three ne ''); $words .= $three; # add 'million', 'thousand' etc $words .= ' ' . $chunks[0] . ' ' if $three; shift @chunks; } } # tidy it up $words =~ m|^\s*(.*?)\s*$|; $words = $1; $words =~ s|\s+| |g; return ($minus ? qq[minus $words] : $words); } sub three_digits { my (@digits, @tens, @teens, $hundreds, $words, $number, $tens, $units, $hyphen); # converts 3-digit number to words @digits = (' ', qw[one two three four five six seven eight nine]); @teens = qw[ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]; @tens = (' ', ' ', qw[twenty thirty forty fifty sixty seventy eighty ninety]); # hundreds $number = shift; $hundreds = int($number / 100); $words = $hundreds ? $digits[$hundreds] . ' hundred' : ''; $number -= $hundreds * 100; # tens and units if ($number) { $words = $words . ' and' if $hundreds != 0; $tens = int($number / 10); $units = $number - 10 * $tens; if ($tens != 1) { $hyphen = ($units and $tens) ? '-' : ''; $words = $words . ' ' . $tens[$tens] . $hyphen . $digits[$units]; } else { $words = $words . ' ' . $teens[$units]; } } # tidy up spaces $words =~ m|^\s*(.*?)\s*$|; $words = $1; $words =~ s|\s+| |g; return $words; }
Input: (6, 7, 8, 9, 10) Output 1: (8, 9, 7, 6, 10) eight; nine; seven; six; ten Output 2: (8, 9, 7, 6, 10) eight; nine; seven; six; ten Input: (-3, 0, 1000, 99) Output 1: (-3, 99, 1000, 0) minus three; ninety-nine; one thousand; zero Output 2: (-3, 99, 1000, 0) minus three; ninety-nine; one thousand; zero Input: (1, -2, 3, -4, 5) Output 1: (5, -4, -2, 1, 3) five; minus four; minus two; one; three Output 2: (5, -4, -2, 1, 3) five; minus four; minus two; one; three Input: (100, 1000, 1000000, 1000000000) Output 1: (1000000000, 100, 1000000, 1000) one billion; one hundred; one million; one thousand Output 2: (1000000000, 100, 1000000, 1000) one billion; one hundred; one million; one thousand Input: (0, 5, 0, 5) Output 1: (5, 5, 0, 0) five; five; zero; zero Output 2: (5, 5, 0, 0) five; five; zero; zero Input: (123, 1000000000000, -999) Output 1: (-999, 123, 1000000000000) minus nine hundred and ninety-nine; one hundred and twenty-three; one trillion Output 2: (-999, 123, 1000000000000) minus nine hundred and ninety-nine; one hundred and twenty-three; one trillion Input: (9, 99, 999, 9999) Output 1: (9, 999, 9999, 99) nine; nine hundred and ninety-nine; nine thousand nine hundred and ninety-nine; ninety-nine Output 2: (9, 999, 9999, 99) nine; nine hundred and ninety-nine; nine thousand nine hundred and ninety-nine; ninety-nine Input: (100123006) Output 1: (100123006) one hundred million, one hundred and twenty-three thousand and six Output 2: (100123006) one hundred million one hundred and twenty-three thousand and six
Any content of this website which has been created by Peter Campbell Smith is in the public domain