#!/usr/bin/perl -w use strict; my \$time = time(); my (%tri,@pos,@pos1,@pos2,@pos3); # make hash of tiangular numbers 5 digits or less # the 447th has 6 digits so we don't map past 446 map{\$tri{.5*\$_*(\$_+1)}=1}1..446; # find all possible matches for 'three' # these are 5 digits long, but last two digits are the same # this allows us to limit the search for my \$key(keys %tri){ push @pos,\$1 if \$key =~/(\d\d\d(\d)\2)/; } # let's see how many possibilities we have print "Initially we have ".@pos." possibles for \\$t\\$h\\$r\\$e\\$e\n"; print "\$_\n" for @pos; # find all possible matches for 'ten' within constraint # of \$t and \$e possibilities generated above, we are looking for 'n' for (@pos) { my(\$t,\$h,\$r,\$e)=split'',\$_; for my \$n(0..9) { push @pos1, "\$t\$h\$r\$e\$n" if defined \$tri{"\$t\$e\$n"} } } # let's see how many possibilities we have left print "\nNext we have ".@pos1." possibles for \\$t\\$h\\$r\\$e\\$n\n"; print "\$_\n" for @pos1; #now look at 'one' in same way, we are looking for 'o' for (@pos1) { my(\$t,\$h,\$r,\$e,\$n)=split'',\$_; for my \$o(0..9) { push @pos2, "\$t\$h\$r\$e\$n\$o" if defined \$tri{"\$o\$n\$e"} } } # let's see how many possibilities we have left print "\nNow we have ".@pos2." possibles for \\$t\\$h\\$r\\$e\\$n\\$o\n"; print "\$_\n" for @pos2; # remove dulicates where digits for \$t\$h\$r\$e\$n\$o are not unique # I'm sure there is something more elegant but this works for (@pos2) { \$_ =~ /(.)(.)(.)(.)(.)(.)/; push @pos3,\$_ if \$_=~m/[^\$2\$3\$4\$5\$6][^\$1\$3\$4\$5\$6][^\$1\$2\$4\$5\$6][^\$1\$2\$3\$5\$6][^\$1\$2\$3\$4\$6][^\$1\$2\$3\$4\$5]/; } # let's see how many possibilities we have left print "\nAfter removing cases where we have duplicate digits\n"; print "we have ".@pos3." possible matches for \\$t\\$h\\$r\\$e\\$n\\$o\n"; print "\$_\n" for @pos3; # find the solution for my \$pos(@pos3) { # get the remaining digits available for 'six' # we erase the 6 digits we are currently using # for t h r e n o my \$remaining = '0123456789'; for (split'',\$pos) {\$remaining =~ s/\$_//;} # look at the remaining cases print "\nBrute forcing\n"; print "If \\$t\\$h\\$r\\$e\\$n\\$o\ is \$pos then \\$s\\$i\\$x must come from \$remaining\n\n"; # brute force possibilities for six, it's only 4 digits my @rem = split'',\$remaining; for my \$s(@rem){ i: for my \$i(@rem){ next i if \$i==\$s; x: for my \$x(@rem) { next x if \$x==\$i or \$x==\$s; if (defined \$tri{"\$s\$i\$x"}){ my(\$t,\$h,\$r,\$e,\$n,\$o)=split'',\$pos; # prove we are right! print "\nfound solution\n"; print "###################################\n"; print "one \$o\$n\$e " if defined \$tri{"\$o\$n\$e"}; print "three \$t\$h\$r\$e\$e " if defined \$tri{"\$t\$h\$r\$e\$e"}; print "six \$s\$i\$x " if defined \$tri{"\$s\$i\$x"}; print "ten \$t\$e\$n\n" if defined \$tri{"\$t\$e\$n"}; print "###################################\n\n"; } else {print "No match \\$s\\$i\\$x -> \$s\$i\$x\n"} } } } } \$time = time()-\$time; print "\nElapsed \$time seconds\n";