# TODO - prototype code only!
my @num2word = qw{zero one two ... twenty};
...
say q{I have }, $num2word[$apple_count], q{ apples.};
####
#!perl
use 5.12.0;
use strict;
use warnings;
my @fixed_test_data = qw{
0 1 2 3 4 5 6 7 8 9 10 11 12 13 114 215 326 437 549 650 1761
19 20 21 29 30 31 89 90 91 95 99
101 1001 1010 10101 11011 11111 101101 110011 110010011 101101101
101010101010101 100100100100100100 100010001000100010001000
100010001 1001001 10000111100001 1230321120210101
expect_fail
999999999999999
9999999999999999
999999999999999999999999999999999999999999999999999999999999999999
1000000000000000000000000000000000000000000000000000000000000000000
9999999999999999999999999999999999999999999999999999999999999999999999999999
100 1000 10000 10000 100000 1000000 1234567890
100000000000000000000
10000000000000000000000000000000000000000
1000000000000000000000000000000000000000000000000000000000000
100000000000000000000000000000000000000000000000000000000000000000
1000000000100000000001000000000001000000000000
};
unshift @fixed_test_data, undef;
my @units = qw{zero one two three four five six seven eight nine};
my @teens = qw{dummy eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen};
my @tens = qw{dummy ten twenty thirty forty fifty sixty seventy eighty ninety};
my %triplet_level = (
0 => q{}, 1 => q{thousand}, 2 => q{million}, 3 => q{billion},
4 => q{trillion}, 5 => q{quadrillion}, 6 => q{quintillion},
7 => q{sextillion}, 8 => q{septillion}, 9 => q{octillion},
10 => q{nonillion}, 11 => q{decillion}, 12 => q{undecillion},
13 => q{duodecillion}, 14 => q{tredecillion}, 15 => q{quattuordecillion},
16 => q{quinquadecillion}, 17 => q{sexdecillion}, 18 => q{septendecillion},
19 => q{octodecillion}, 20 => q{novendecillion}, 21 => q{vigintillion},
);
my $highest_triplet_level = (sort { $b <=> $a } keys %triplet_level)[0];
my $highest_number_length = $highest_triplet_level * 3 + 3;
print q{Run fixed tests (y/n): };
if (<> =~ m{ \A y }imsx) {
for my $num (@fixed_test_data) {
my $lhs = $num // q{undef};
say qq{$lhs = }, conv_num_to_text($num);
}
}
print q{Run manual tests (y/n): };
if (<> =~ m{ \A y }imsx) {
while (my $num = <>) {
chomp $num;
say qq{$num = }, conv_num_to_text($num);
}
}
sub conv_num_to_text {
my $num = shift;
if (! defined $num) {
return q{GIGO: No number supplied, so no conversion to text!};
}
chomp $num;
if ($num !~ m{ \A \d+ \z }msx) {
return qq{IGNORED: $num is not a positive integer!};
}
if (length($num) > $highest_number_length) {
return q{WARNING: Number too long!}
. qq{ Most digits currently allowed is: $highest_number_length}
. q{ [Your input had } . length($num) . q{ digits]};
}
my @digits = split m{}msx => $num;
if ($#digits == 0) {
return $units[$num];
}
return _get_triplets(\@digits);
}
sub _get_triplets {
my ($ra_digits, $level, $ra_text) = @_;
$level //= 0;
$ra_text //= [];
# Escape clause
if ($#$ra_digits < 0) {
my $front_text = join q{, } => grep { length } @$ra_text[0 .. $#$ra_text - 1];
my $last_element = $ra_text->[$#$ra_text];
if ($front_text and $last_element =~ m{ hundred }msx) {
$front_text .= qq{,};
}
return join q{ } => grep { length } ($front_text, $last_element);
}
# Canonicalise data
while ( $#$ra_digits < 2 ) {
unshift @$ra_digits => 0;
}
# Process tail three digits
my ($hun_digit, $ten_digit, $unit_digit) = @$ra_digits[-3, -2, -1];
$#$ra_digits -= 3;
my $string = q{};
if ($hun_digit) {
$string .= qq{$units[$hun_digit] hundred};
if ($ten_digit + $unit_digit) {
$string .= q{ and };
}
}
else {
if ($level == 0 && $#$ra_digits >= 0 && $ten_digit + $unit_digit) {
$string .= q{and };
}
}
if ($ten_digit) {
if ($ten_digit == 1 and $unit_digit) {
$string .= $teens[$unit_digit];
}
else {
$string .= $tens[$ten_digit];
if ($unit_digit) {
$string .= qq{-$units[$unit_digit]};
}
}
}
else {
if ($unit_digit) {
$string .= qq{$units[$unit_digit]};
}
}
if ($level) {
if ($hun_digit + $ten_digit + $unit_digit) {
$string .= qq[ $triplet_level{$level}];
}
}
# Recurse with remaining digits
return _get_triplets([@$ra_digits], $level + 1, [$string, @$ra_text]);
}
####
$ perl -Mstrict -wE 'use Number::Spell; say spell_number(100010001001)'
one hundred billion ten million one thousand one
$ perl -Mstrict -wE 'use Lingua::EN::Numbers qw{num2en}; say num2en(100010001001)'
one hundred billion, ten million, one thousand and, one
$ perl -Mstrict -wE 'use Util::Number; say conv_num_to_text(100010001001)'
one hundred billion, ten million, one thousand and one