''This page was spun off from [Solving cryptarithms], numeric puzzles in which digits have been replaced by letters'' ---- [TFW] (Feb, 23 2004) - Got frustrated helping my 5th grade son solve some extra credit homework. We must solve the equation below where ABCDE*4=EDCBA, nothing fancy but the brute force methods solved it before your finger leaves the keyboard. #---------------------------------------------------------------------------- # Solve the problem # ABCDE # X4 #------ # EDCBA #---------------------------------------------------------------------------- proc ABCDE {args} { set nums {1 2 3 4 5 6 7 8 9} set counter 0 foreach a $nums { foreach b $nums { foreach c $nums { foreach d $nums { foreach e $nums { set n1 [expr {"$a$b$c$d$e"*4}] set n2 "$e$d$c$b$a" incr counter if {$n1==$n2} { puts "We solved it! $a$b$c$d$e * 4 = $n2 at $counter tries" return } } } } } } puts "Not Solved" } Here is another one, we have $1 in coins but only one can be a nickel. So we know that 19 coins must add to 95 cents using only pennies, dimes, quarters and half-dollars. Again, the simple brute force method yields an answer before your finger leaves the keyboard #---------------------------------------------------------------------------- # Solve the problem # 20 coins = $1.00, only one is a nickel # so we have 19 coins =95 cents #---------------------------------------------------------------------------- proc solve2 {args} { set nums {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19} set counter 0 foreach penny $nums { foreach dime $nums { foreach quarter $nums { foreach halfdollar $nums { if {($penny+$dime+$quarter+$halfdollar)==19} { set value [expr {$penny*1+$dime*10+$quarter*25+$halfdollar*50}] incr counter if {$value==95} { puts "We solved it! penny=$penny dime=$dime quarter=$quarter halfdollar=$halfdollar at $counter tries" return } } } } } } puts "Not Solved" } ---- [RS] experiments with the following "General Problem Solver" (for small values of General), which, with heavy [metaprogramming], builds up a nest of [foreach]s suiting the problem, quick kills (with [continue]) to force unique values for the variables, and returns the first solution found, or else an empty string: proc solve {problem {domain0 {0 1 2 3 4 5 6 7 8 9}}} { set vars [lsort -u [split [regsub -all {[^A-Z]} $problem ""] ""]] set map {= ==} set outers {} set initials [regexp -all -inline {[^A-Z]([A-Z])} /$problem] set pos [lsearch $domain0 0] set domain1 [lreplace $domain0 $pos $pos] foreach var $vars { append body "foreach $var \$domain[expr [lsearch $initials $var]>=0] \{\n" lappend map $var $$var foreach outer $outers { append body "if {$$var eq $$outer} continue\n" } lappend outers $var append epilog \} } set test [string map $map $problem] append body "if {\[expr $test\]} {return \[subst $test\]}" $epilog if 1 $body } This passes the tests from earlier in this page: % solve SEND+MORE=MONEY 9567+1085==10652 % solve SAVE+MORE=MONEY 9386+1076==10462 % solve YELLOW+YELLOW+RED=ORANGE 143329+143329+846==287504 So this routine is not blindingly fast, but can process a number of problems from earlier in this page, without other configuration than specifying the problem. Another kind of cryptarithm I found in Martin Gardner's ''Mathematical Circus'': EVE/DID=.TALKTALKTALK... requires epsilon comparison with a periodic fraction... Any takers? - Took it myself, by replacing == equality with abs(delta)=0] \{\n" lappend map $var $$var foreach outer $outers { append body "if {$$var eq $$outer} continue\n" } lappend outers $var append epilog \} } set test abs(([string map $map $problem]))<=.00000001 append body "if {\[expr $test\]} {return \[subst $test\]}" $epilog if 1 $body } ---- The other tests still pass, but the output is a bit harder to read: % solve EVE/DID.=.TALKTALK... abs((212/606.)-(.34983498))<=.00000001 % solve SEND+MORE=MONEY abs((9567+1085)-(10652))<=.00000001 % solve ABCDE*4=EDCBA abs((21978*4)-(87912))<=.00000001 % solve 7AB*CD=EFGHJ abs((713*59)-(42067))<=.00000001 The last example comes wrong, because the fixed "7" in front is re-used for J in the end. ---- ''[PWQ] 25 Feb 04'', Can ''TFW'' please post an example of the problem: 7ab * cd = efghi? I tried a version, but my fingers have finished typing and I am still waiting for an answer. Thanks. ---- ''[TFW] 25 Feb 04'', OK here is one that solves 7AB*CD=EFGHI (without reusing the 7 and no duplicates) proc 7AB {args} { set nums {0 1 2 3 4 5 6 7 8 9} foreach A $nums { if {[string first $A "70"]>=0} continue foreach B $nums { if {[string first $B "70$A"]>=0} continue foreach C $nums { if {[string first $C "70$A$B"]>=0} continue foreach D $nums { if {[string first $D "7$A$B$C"]>=0} continue foreach E $nums { if {[string first $E "70$A$B$C$D"]>=0} continue foreach F $nums { if {[string first $F "7$A$B$C$D$E"]>=0} continue foreach G $nums { if {[string first $G "7$A$B$C$D$E$F"]>=0} continue foreach H $nums { if {[string first $H "7$A$B$C$D$E$F$G"]>=0} continue foreach I $nums { if {[string first $I "7$A$B$C$D$E$F$G$H"]>=0} continue if {"7$A$B" * "$C$D"=="$E$F$G$H$I"} { return "7$A$B*$C$D==$E$F$G$H$I" } } } } } } } } } } } PS. The answer is 715*46==32890 ---- [RS] got that too (with the first ''solve'' version), after respecifying the problem in a slightly clumsy way, and 27 minutes: % solve Z=7&&ZAB*CD=EFGHI 7==7&&715*46==32890 ----