我被要求使用Prolog解决一个密码算术:
GIVE
* ME
------
MONEY
以上是谜题,我无法弄清楚问题出在哪里,结果总是返回false。另外,我不允许在SWI-Prolog中使用任何库。
solve(Z) :-
assign(Z,[0,1,2,3,4,5,6,7,8,9]),
check(Z).
find( VAL , G,I,V,E ) :- VAL is G * 1000 + I * 100 + V * 10 + E.
find2(VALR, M,E ) :- VALR is M * 10 + E.
find3(VALA, M,O,N,E,Y) :- VALA is M * 10000 + O * 1000 + N * 100 + E * 10 + Y.
check(Z) :-
G #>= 1,
M #>= 1,
find( VAL, G,I,V,E),
find2(VALR, M,E),
find3(VALA, M,O,N,E,Y),
VAL * VALR =:= VALA.
assign(Z,L) :-
permute(L,Z).
/* permute is similar to all_different in swi-prolog */
addany(X,K,[X|K]).
addany(X,[F|K],[F|L1]) :-
addany(X,K,L1).
permute([],[]).
permute([X|K],P) :-
permute(K,L1),
addany(X,L1,P).
示例查询:
?- solve([G,I,V,E,M,O,N,Y]).
false. % fails unexpectedly
答案 0 :(得分:2)
让我们了解问题的核心!
[0,1,2,3,4,5,6,7,8,9]
是长度10 的列表。[G,I,V,E,M,O,N,Y]
是长度为8 的列表。[0,1,2,3,4,5,6,7,8,9]
没有[G,I,V,E,M,O,N,Y]
的排列可以与check/1
统一。作为快速解决方法,请按照以下方式调整:- use_module(library(clpfd)).
的定义:
check([G,I,V,E,M,O,N,Y,_,_]) :- find( VAL, G,I,V,E), G >= 1, find2(VALR, M,E), M >= 1, find3(VALA, M,O,N,E,Y), VAL * VALR =:= VALA.
然后,运行以下“修复”查询:
?- Expr = ([G,I,V,E]*[M,E] = [M,O,N,E,Y]), Zs = [G,I,V,E,M,O,N,Y,_,_], time(solve(Zs)). % 24,641,436 inferences, 7.692 CPU in 7.709 seconds (100% CPU, 3203506 Lips) Expr = ([1,0,7,2] * [9,2] = [9,8,6,2,4]), Zs = [1,0,7,2,9,8,6,4,3,5] ; % 7,355 inferences, 0.007 CPU in 0.007 seconds (100% CPU, 1058235 Lips) Expr = ([1,0,7,2] * [9,2] = [9,8,6,2,4]), % redundant Zs = [1,0,7,2,9,8,6,4,5,3] ; % 6,169,314 inferences, 1.935 CPU in 1.939 seconds (100% CPU, 3188312 Lips) Expr = ([1,0,9,2] * [7,2] = [7,8,6,2,4]), Zs = [1,0,9,2,7,8,6,4,3,5] ; % 7,355 inferences, 0.005 CPU in 0.005 seconds (99% CPU, 1360603 Lips) Expr = ([1,0,9,2] * [7,2] = [7,8,6,2,4]), % redundant Zs = [1,0,9,2,7,8,6,4,5,3] ; % 6,234,555 inferences, 1.955 CPU in 1.959 seconds (100% CPU, 3189462 Lips) false.
这是解决问题的另一种方法:
首先,使用clpfd!
"hd1440"
其次,(重新)使用前面my answer中提供的代码 相关问题Faster implementation of verbal arithmetic in Prolog:
?- Expr = ([G,I,V,E] * [M,E] #= [M,O,N,E,Y]), Zs = [G,I,V,E,M,O,N,Y], crypt_arith_(Expr,Zs), time(labeling([],Zs)). % 397,472 inferences, 0.088 CPU in 0.088 seconds (100% CPU, 4521899 Lips) Expr = ([1,0,7,2] * [9,2] #= [9,8,6,2,4]), Zs = [1,0,7,2,9,8,6,4] ; % 128,982 inferences, 0.037 CPU in 0.037 seconds (100% CPU, 3502788 Lips) Expr = ([1,0,9,2] * [7,2] #= [7,8,6,2,4]), Zs = [1,0,9,2,7,8,6,4] ; % 77,809 inferences, 0.028 CPU in 0.028 seconds (100% CPU, 2771783 Lips) false.
没有多余的解决方案。比“生成和测试”更快的数量级。 clpfd岩石!
答案 1 :(得分:0)
Eric Weisstein和Ed Pegg的以下article将非常有用。它为Mathematica中的类似问题提供了几种解决方案。
使用非常强力的方法,有两种解决方案:1072 * 92 = 98624
和1092 * 72 = 78624
。我使用的代码:
In[16]:= Cases[
Permutations[
Range[0, 9], {5}], {g_, i_, v_, e_, m_} /; g > 0 && m > 0 :>
With[{dig = IntegerDigits[(g*10^3 + i*10^2 + v*10 + e) (10 m + e)]},
Join[{g, i, v, e, m}, dig[[{2, 3, 5}]]] /;
And[Length[dig] == 5, Unequal @@ dig, dig[[{1, 4}]] == {m, e},
Intersection[dig[[{2, 3, 5}]], {g, i, v, e, m}] === {} ]
]]
Out[16]= {{1, 0, 7, 2, 9, 8, 6, 4}, {1, 0, 9, 2, 7, 8, 6, 4}}