/* General alphametic (cryptarithmetic) solver in Picat. This is a fairly general solver for alphametic problems, but it requires explicit variables. E.g. alphametic([[S,E,N,D],[M,O,R,E],[M,O,N,E,Y]], Base, Res) Model created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go => go1, go2, go3. go1 => Base = 10, % SEND + MORE = MONEY L = [[_S,E,N,_D],[M,O,_R,E],[M,O,N,E,_Y]], alphametic(L, Base, Res), writeln(Res), writeln(L), print_res(L). go2 => Base = 10, % DONALD + GERALD = ROBERT Problem = [[D,O,_N,A,L,D],[_G,E,R,A,L,D],[R,O,_B,E,R,_T]], alphametic(Problem, Base, Res), writeln(Res), writeln(Problem), print_res(Problem). go3 => Base = 10, % SATURN+URANUS+NEPTUNE+PLUTO=PLANETS Problem = [[S,A,T,U,R,N], [U,R,A,N,U,S], [N,E,P,T,U,N,E], [P,L,U,T,_O], [P,L,A,N,E,T,S]], alphametic(Problem, Base, Res), writeln(Res), writeln(Problem), print_res(Problem). term_variables(L) = Flatten => Flatten1 = [], foreach(LL in L) Flatten1 := Flatten1 ++ LL end, Flatten2 = remove_dups(Flatten1), Flatten = Flatten2. alphametic(L,Base, Vars) => Rev = reverse(L), Rev = [Last|Sums], Vars = L.vars, % term_variables(L), Vars :: 0..Base-1, all_different(Vars), Vals #= sum([Val : S in Sums, Val = calc(S,Base)]), Vals = calc(Last,Base), foreach(S in Sums) S[1] #> 0 end, solve([ff,split], Vars). calc(X,Base) = Y => Len = length(X), Y #= sum([X[I]*Base**(Len-I) : I in 1..Len]). print_res(L) => Rev = reverse(L), Rev = [Last|Sums], Sums2 = reverse(Sums), foreach(S in Sums2) print_single(S) end, print_single(Last), nl. print_single(L) => foreach(S in L) writef("%d",S) end, writef("\n").