#! /usr/bin/perl use strict; use warnings; use Data::Dumper; # just for debugging... use Algorithm::Loops qw(NestedLoops); use List::Util; use Time::HiRes qw(gettimeofday tv_interval); my $t0 = [gettimeofday]; my @words = readwords(\*DATA); # Calculate the letters in each - do this up front for speed? my %letters_cache; foreach my $inner (@words) { foreach my $word (@$inner) { my %letters; foreach (split '', $word) { $letters{$_}++; } $letters_cache{$word} = \%letters; } } my @best_words; my $best_score = 0; my $iter = NestedLoops(\@words); my $count = 0; while (my @list = $iter->()) { ++$count; my @words = @list; my $score = calculate_score(@words); if ($score > $best_score) { $best_score = $score; @best_words = @list; } my $t_now = tv_interval($t0, [gettimeofday]); if ($count % 15 == 0) { local $|=1; print "$count\r"; } }; my $elapsed = tv_interval($t0, [gettimeofday]); print "The best score is $best_score, using the words:\n", map { "\t$_\n" } @best_words; print "Elapsed time: $elapsed seconds\n"; #print Dumper(\%letters_cache); sub calculate_score { my $total = 0; my %letters; foreach my $w (@_) { $w = $letters_cache{$w} unless ref $w; while (my ($l,$n) = each %$w) { $letters{$l} += $n; } } # add them up. our ($a,$b); # get rid of warning? List::Util::reduce { $a + calculate_letter_value($b) } 0, values %letters; } sub calculate_letter_value { my $n = shift; ($n * ($n + 1)) / 2; } # slurp in all the possible words. sub readwords { my $fh = shift; unless (ref $fh) { require IO::File; $fh = IO::File->new($fh, 'r') || die "Can't open $fh for read: $!"; } local $_; my @words; while (<$fh>) { my ($num, $word) = split ' ', lc; push @{$words[$num-1]}, $word; } @words; } __DATA__ 1 alabama 1 arkansas 1 alaska 1 delaware 1 hawaii 1 indiana 1 kansas 1 montana 1 delaware 2 sazerac 2 sangrita 3 radiator 3 gastank 3 engine 3 heater 3 fender 3 wheel 3 detent 3 battery 3 clutch 3 mirror 3 window 4 alloy 4 amalgam 4 vanadium 4 copper 4 steel 5 rutabaga 5 limabean 5 cress 5 carrot 5 sorrel 5 squash 5 cabbage 5 pepper 5 lettuce 5 beet 5 leek 5 celery 5 endive 5 rhubarb 5 parsnip 5 pumpkin 6 azalia 6 camellia 6 dahlia 6 gardenia 6 gentian 6 vervain 6 canna 6 hepatica 6 bluebell 6 anemone 6 oleander 7 lasagna 7 macaroni 7 pastina 7 gnocchi 7 tortelli 7 alfabeto 8 mascagni 8 britten 8 menotti 9 unamas 9 tacotime 9 pizzahut 9 tacobell 9 panago 9 tacomayo 9 edojapan 9 hardees 10 caramel 10 marzipan 10 taiglach 10 taffy 10 brittle 10 fondant 10 toffee 10 dragee #### 1 alabama 1 arkansas 2 sangrita 3 radiator 3 gastank 4 amalgam 4 vanadium 5 rutabaga 5 limabean 6 azalia 6 camellia 6 dahlia 6 gardenia 7 lasagna 7 macaroni 7 pastina 8 mascagni 9 unamas 10 caramel 10 marzipan 10 taiglach #### The best score is 474, using the words: alabama sangrita gastank amalgam rutabaga azalia lasagna mascagni unamas taiglach