Криптоарифметический решатель головоломок с использованием библиотеки CLPFD - PullRequest
1 голос
/ 07 апреля 2019

Я видел несколько примеров решателя кирптарифметических головоломок с использованием библиотеки Prolog clfpd. Например, если у меня есть головоломка AM + PM = DAY, она может назначать разные наборы значений от 0 до 9 различным алфавитам, чтобы A * 10 + M + P * 10 + M = D * 100 + A * 10 + Y , Я пытаюсь написать обобщенную версию этого. Обратите внимание, что у меня очень мало опыта работы с Prolog или clfpd.

Я намерен создать ограничения на основе ввода. Например, A * 10 + M + P * 10 + M = D * 100 + A * 10 + Y должно быть сгенерировано на основе входной головоломки1 ([A, M] + [P, M] = [D, A, Y ]). Но я понятия не имею, как это сделать. Я написал функцию Пролог (называемую конвертированием), которая на основе ввода создает ограничение. Но это не работает, и я продолжаю получать ошибку

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.

Может ли кто-нибудь направить меня в правильном направлении.

Ответы [ 2 ]

2 голосов
/ 08 апреля 2019

В вашем коде есть две ошибки.Во-первых, convert / 2 - это предикат с двумя аргументами - вы не можете использовать его как функцию.Таким образом, вместо

Exp01 #= convert(As)

просто напишите

convert(As, Exp01)

Другая ошибка:

As #= [H1|_]

Здесь вы хотите структурно разложить список As и извлечьего первый элемент.Это можно сделать простым объединением, т.е.

As = [H1|_]

Разница в том, что #= реализует (целочисленное) арифметическое равенство (то есть интерпретирует обе стороны как арифметические выражения), тогда как =Чистая символическая манипуляция, которая вам здесь нужна.

Вы можете найти программу, похожую на вашу, на http://eclipseclp.org/examples/cryptarith.ecl.txt

0 голосов
/ 08 апреля 2019

Рабочий код:

:- 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 is N-1, 
    multiple(N1,F1), 
    F is 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 is Len1-1,
    multiple(Len2,Multiplier),
    convert(T, Ans1),
    Ans = Ans1 + H * Multiplier.


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),
   convert(As, Ans1),
   convert(Bs, Ans2),
   convert(Cs, Ans3),
   %Generates a constraint depending on the input
   %For instance if input is puzzle1([A,M] + [P,M] = [D,A,Y])
   %Output constraint = A*10 + M + P*10 + M  = D*100 + A*10 + Y 
   Ans1 + Ans2 #= Ans3,
   As = [H1|_],
   Bs = [H2|_],
   H1 #\=0,
   H2 #\=0,
   label(Var),
   write("Solution: "),
   write(As + Bs = Cs).


%puzzle1([A,M]+[P,M]=[D,A,Y]).
%puzzle1([A,M]+[I]=[O,K]).
%puzzle1([Y,O,U]+[A,R,E]=[D,O,N,E]).
%puzzle1([S,E,N,D]+[M,O,R,E]=[M,O,N,E,Y]).
%puzzle1([R,O,A,D]+[I,N]=[U,S,A]).
%puzzle1([B,I,K,E]+[F,O,R]=[R,I,D,E]).
...