使用谓词在序言中解决 kakuro

时间:2021-01-14 16:16:34

标签: prolog

我想谓词解决 Kakuro。
我的 kakuro 是这个 enter image description here

我必须使用单词 solve (solve/1) 为游戏 kakuro 创建一个谓词。我尝试了 3-4 个代码,所有代码都有错误。变量必须在 1-9 之间(A 值在 1-9 之间)并且所有变量必须在一行和列中不同(24=A+B+C 而不是 24=A+A+C)。

第一个代码是:

:- use_module(library(clpfd)).
solve(L):-
    L= [A,B,C,E,F,G,J,K,L,N,O,P],
    all_different(L),
   L ins 1..9,
    A #= 24-B-C,
    B #= 26-F-J-N,
    C #= 15-G-K-O,
    E #= 11-F-G,
    E #= 17-A,
    J #= 22-K-L,
    N #= 14-O-P,
    L #= 13-P.

第二个代码:

:- use_module(library(clpfd)).
sum_list([],0).
sum_list([Head|Tail], Sum):-sum_list(Tail, Sum1),Sum is Head+Sum1.

go:-
    Vars=[A,B,C,E,F,G,J,K,L,N,O,P],
    Vars ins 1..9,
    word([A,B,C],24),
    word([B,F,J,N],26),
    word([C,G,K,O],15), 
    word([E,F,G],11),
    word([A,E],17),
    word([J,K,L],22),
    word([N,O,P],14),   
    word([L,P],13),
    labeling(Vars),
    writeln(Vars).

word(L,Sum):-
sum_list(L,X),
X=:=Sum,
all_different(L).

第三个代码:

:- use_module(library(clpfd)).
 kakuro(L):-
      L = [A,B,C,E,F,G,J,K,L,N,O,P],
      L ins 1..9,       
      Z1 = [A,B,C],
      all_different(Z1),
      A =:= 24-B-C,     
      Z2 = [B,F,J,N],
      all_different(Z2),
      B =:=26-F-J-N,
      Z3 = [C,G,K,O],
      all_different(Z3),
      C =:= 15-G-K-O,
      Z4 = [E,F,G],
      all_different(Z4),
      E =:= 11-F-G,
      Z5 = [A,E],
      all_different(Z5),
      E =:= 17-A,
      Z6 = [J,K,L],
      all_different(Z6),
      J =:=22-K-L,
      A1 = [N,O,P],
      all_different(A1),
      N =:= 14-O-P,
      A2 = [L,P],
      all_different(A2),
      L =:=13-P,
      labeling([], L).

另外,我该如何开始求解过程?它会像:?-solve(L). ?? L ins 1..9 也不起作用。 enter image description here

2 个答案:

答案 0 :(得分:4)

以下是基于 DuDa 的解决方案,但使用了 sum/3 约束并将标签延迟到最后。这使得解决方案更高效、更具声明性。

:- use_module(library(clpfd)).

kakuro(Vars):-
    Vars=[A,B,C,E,F,G,J,K,L,N,O,P],
    Vars ins 1..9,
    word([A,B,C],24), 
    word([B,F,J,N],26),
    word([C,G,K,O],15), 
    word([E,F,G],11),
    word([A,E],17),
    word([J,K,L],22),
    word([N,O,P],14),   
    word([L,P],13),
    labeling([],Vars).

word(L,Sum):-
    all_different(L),
    sum(L,#=,Sum).

答案 1 :(得分:1)

首先在解决 ins/labeling 问题之前:您的代码 #1 和 #3 存在问题。在代码#1 中,您声明所有变量都需要具有不同的值。这不会提供有效的解决方案。在代码 #1 和 #3 中,您曾经使用变量 L 作为变量的容器,并使用一次作为一个元素。

我已经用 Swish 测试了我的代码。这是代码:

:- use_module(library(clpfd)).

sum_list([],0).
sum_list([Head|Tail], Sum):-
    sum_list(Tail, Sum1),
    Sum is Head+Sum1.

kakuro(Vars):-
    Vars=[A,B,C,E,F,G,J,K,L,N,O,P],
    Vars ins 1..9,
    word([A,B,C],24), 
    word([B,F,J,N],26),
    word([C,G,K,O],15), 
    word([E,F,G],11),
    word([A,E],17),
    word([J,K,L],22),
    word([N,O,P],14),   
    word([L,P],13),
    writeln(Vars).

word(L,Sum):-
    labeling([],L),
    all_different(L),
    sum_list(L,Sum).

这是 ?- kakuro(L). 的(唯一)输出:

[9, 8, 7, 8, 2, 1, 9, 5, 8, 7, 2, 5]

首先,您需要运行 ins/2 谓词。这应该适用于 SWI prolog。其次,您知道如何处理 labeling/2 谓词。这将设置从他们的域(通过 ins/2 给出)给条目的值。在 SWI Prolog 中,第一个属性是选项列表,无需担心。 AFTER 标记变量后,您可以“测试”它们并对它们施加约束。您可以在开始时对所有变量进行一次标记,但这非常缓慢,因为您的所有进度都丢失了。所以我建议在 word/2 谓词中进行。如果出现死胡同,回溯将返回到 word/2 谓词而不是 kakuro/1 谓词的开头。

相关问题