CUFP
YuckFoo
The boy learned about variables the other day and thought it was cool
how letters could stand for numbers. I was reminded of the word math
puzzles I had seen where you have to figure out what digit each letter
represents to make a valid math problem, like:
<code>
one
+ four
========
five
</code>
<code>
spec
+ perl
========
opus
</code>
And so became the word math program. It's just a brute force thing, but kinda cool. <p>
Yuck+Foo
<code>
#!/usr/bin/perl
use strict;
use Data::Dumper;
my $DictFile = '/usr/share/dict/words';
my $MinLen = 3;
my $MaxLen = 6;
my $Todo = 10;
my $Hint = 1;
my $dict = read_dict($DictFile, $MinLen, $MaxLen);
#my $dict = read_data($MinLen, $MaxLen);
my $pre_selects = (@ARGV) ? [@ARGV] : [];
while ($Todo) {
my $words = choose_words($dict, $pre_selects);
my $numbs = encode_words($words);
if ($numbs) {
($words, $numbs) = sort_lists($words, $numbs);
if ($numbs->[0] + $numbs->[1] == $numbs->[2]) {
$Todo--;
show_it($MaxLen, $words, $numbs, $Hint);
}
}
}
#-----------------------------------------------------------
sub show_it {
my $len = shift;
my $words = shift;
my $numbs = shift;
my $hint = shift;
$hint = ($hint) ? make_hint($words, $numbs) : '';
printf " %*s\n", $len, $words->[0];
for my $i (1..@$words-2) {
printf "+ %*s\n", $len, $words->[$i];
}
printf "==%s\n", '=' x $len;
printf " %*s $hint\n\n", $len, $words->[-1];
}
#-----------------------------------------------------------
sub make_hint {
my $words = shift;
my $numbs = shift;
my $w_str = join('', @$words);
my $n_str = join('', @$numbs);
my $r = rand(length($w_str));
my $w = substr($w_str, $r, 1);
my $n = substr($n_str, $r, 1);
return "($w = $n)";
}
#-----------------------------------------------------------
sub sort_lists {
my $words = shift;
my $numbs = shift;
my @list;
for my $i (0..@$numbs - 1) {
push @list, {
i => $i,
numb => $numbs->[$i],
};
}
@list = sort { $a->{numb} <=> $b->{numb} } @list;
my (@new_words, @new_numbs);
while (my $i = shift(@list)) {
push @new_words, $words->[$i->{i}];
push @new_numbs, $numbs->[$i->{i}];
}
return (\@new_words, \@new_numbs);
}
#-----------------------------------------------------------
sub encode_words {
my $words = shift;
my %letters;
my @numbs;
for my $word (@$words) {
for my $char (split('', $word)) {
$letters{$char}++;
}
}
my @letters = keys(%letters);
(@letters > 9) and return;
my @digits = (0..9);
my %xlate = {};
while (my $letter = splice(@letters, rand(@letters), 1)) {
$xlate{$letter} = splice(@digits, rand(@digits), 1);
}
for my $word (@$words) {
my $numb;
for my $char (split('', $word)) {
$numb .= $xlate{$char};
}
push @numbs, $numb;
}
return \@numbs;
}
#-----------------------------------------------------------
sub choose_words {
my $dict = shift;
my $words = shift;
my @list = @$words;
while (@list < 3) {
push @list, $dict->[rand(@$dict)];
}
return \@list;
}
#-----------------------------------------------------------
sub read_dict {
my $file = shift;
my $min = shift;
my $max = shift;
my @words;
open (my $fh, '<', $file) or die;
while (my $line = <$fh>) {
chomp $line;
(length($line) < $min) and next;
(length($line) > $max) and next;
($line =~ tr/A-Z/A-Z/) and next;
push @words, $line;
}
return \@words;
}
#-----------------------------------------------------------
sub read_data {
my $min = shift;
my $max = shift;
my @words;
while (my $line = <DATA>) {
chomp $line;
(length($line) < $min) and next;
(length($line) > $max) and next;
($line =~ tr/A-Z/A-Z/) and next;
push @words, $line;
}
return \@words;
}
__DATA__
zero
one
two
three
four
five
six
seven
eight
nine
ten
eleven
twelve
thirteen
fourteen
fifteen
sixteen
seventeen
eighteen
nineteen
twenty
</code>