I have seen some examples of cyrptarithmetic puzzle solver using Prolog's clfpd library. For instance if I have a puzzle AM + PM = DAY, it can assign different set of values from 0 to 9 to different alphabets so that A*10+M + P*10+M = D*100+A*10+Y. I am trying to write a generalized version of it. Please note that I have very little experience with either Prolog or clfpd.
I intend to generate constraints based on input. For instance A*10+M + P*10+M = D*100+A*10+Y is to be generated based in input puzzle1([A,M]+[P,M]=[D,A,Y]). But I have no idea how to do it. I have written a Prolog function (called convert) which based on input creates a constraint. But its not working and I keep getting error
clpfd_expression' expected, found `convert([_818,_894])
:- use_module(library(clpfd)).
%calculate correct multiplier
%For example if AM, multipler of A is 10 and of M is 1
multiple(1,10).
multiple(N,F) :-
N#>0,
N1 #= N-1,
multiple(N1,F1),
F #= 10 * F1.
%convert accepts input as a list. For instance [A,M]
%outputs a constraint of the form A*10 + M*1
convert([H|T], Ans):-
length(T, Len),
Len #= 0,
Ans #= H * 1.
convert([H|T], Ans):-
length([H|T], Len1),
Len2 #= Len1-1,
multiple(Len2,Multiplier),
convert(T, Ans1),
Ans #= Ans1 + H * Multiplier.
%add should imply constraint A*10+M+P*10+M=D*100+A*10+Y.
add(Exp1, Exp2, Exp3):-
Exp1 + Exp2 #= Exp3.
puzzle1(As + Bs = Cs) :-
append([As,Bs,Cs],Ds),
term_variables(Ds,Var), %% this will get all Var
Var ins 0..9,
all_different(Var),
Exp01 #= convert(As),
Exp02 #= convert(Bs),
Exp03 #= convert(Cs),
add(Exp01, Exp02, Exp03),
%add constraint first member of each list cant be asigned a value 0
As #= [H1|_],
Bs #= [H2|_],
Cs #= [H3|_],
H1 #\=0,
H2 #\=0,
H3 #\=0.
Can someone steer me in correct direction.
There are two mistakes in your code. First, convert/2 is a predicate with two arguments -- you cannot use it as a function. So, instead of
simply write
The other mistake is
Here you want to structurally decompose the list
Asand extract its first element. The way to do that is with simple unification, i.e.The difference is that
#=implements (integer) arithmetic equality (meaning that it interprets both sides as arithmetic expressions), while=is pure symbolic manipulation, which is what you want here.You can find a program similar to yours at http://eclipseclp.org/examples/cryptarith.ecl.txt