Sunday, August 2, 2009

Project Euler #17

Euler Project #17: "If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

"If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?"

Their notes say something about "and" in numbers British-style, but I have ignored this as I have no idea where the ands would go.
use v6;
my %number_names = (
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
6 => "six",
7 => "seven",
8 => "eight",
9 => "nine",
10 => "ten",
11 => "eleven",
12 => "twelve",
13 => "thirteen",
14 => "fourteen",
15 => "fifteen",
16 => "sixteen",
17 => "seventeen",
18 => "eighteen",
19 => "nineteen",
20 => "twenty",
30 => "thirty",
40 => "forty",
50 => "fifty",
60 => "sixty",
70 => "seventy",
80 => "eighty",
90 => "ninety"
);
for 1..9 -> $n
{
%number_names{$n * 100} = %number_names{$n} ~ " hundred";
}
sub NumberName(%number_names, $number)
{
given $number
{
when 0 { return "zero"; }
when 1000 { return "one thousand"; }
}
my $n = $number;
my $name = "";
while ($n > 0)
{
$name ~= " " if $name.chars > 0;
my $biggest = %number_names.keys.grep({$_ <= $n}).map({+$_}).max;
$name ~= %number_names{$biggest};
$n -= $biggest;
}
return $name;
}
my $letter = 0;
for 1..1000 -> $number
{
my $name = NumberName(%number_names, $number);
# say "$number => $name";
$name.subst(rx/<alpha>/, { $letter++ }, :g);
}
say $letter;
view raw euler_017_01.pl hosted with ❤ by GitHub

This is a slow, stupid way to solve this problem. (Though I'm reasonably happy with it as an example of Perl 6 programming.) On the other hand, this way of doing it makes it much easier to check for correctness. (Though I discovered I'd misspelled one of the numbers in the process of posting this. Sigh.) This runs in just over 3 minutes on my MBP. I will be very disappointed if I can't get that time below 20 seconds. But that is a matter for a future post.

PS I would really like to use Yuval Kogman's system for cleaning up / speeding up Gist embedding in blog posts. Unfortunately, I can't quite make sense of what he is actually doing. Afraid I have fallen a bit behind the technological curve here...

2 comments:

  1. If using Perl 5, this problem just begs for some
    CPAN leverage:

    use 5.10.0;

    use Lingua::EN::Numbers qw/ num2en /;
    use List::Util qw/ sum /;

    say sum map { y/a-z// } map { num2en( $_ ) } 1..1000;

    :-)

    ReplyDelete
  2. Ha! Yes, as always, you can get rather drastic improvements by using CPAN.

    ReplyDelete