# 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