序言中的八位数难题

时间:2018-07-31 08:46:09

标签: prolog clpfd

我正试图弄清楚如何在序言中解决以下难题。

我需要创建一个谓词seven_digit_puzzle(Result)。提出了遵循以下规则的八位数难题的所有可能解决方案:

  • 每个单元格包含1到8之间的数字。
  • 没有重复。
  • 在四个方向的每个单元格中,不能放置连续的数字(它们之间的差为1的数字)。

    例如,从视觉上看,谓词的结果在序言中:

example

结果= [7,4,1,3,6,8,5,2]

2 个答案:

答案 0 :(得分:3)

您可以使用CLP(FD)解决问题。条件 两个相邻单元格之间的距离不为一 无需表达即可表达:

ns(X, Y) :- 
    X #\= Y+1, 
    X+1 #\= Y.

由于当前情况,无需进行修改 (#/ \)/ 2可以用(,)/ 2代替。与all_different / 1一起,该问题可以表示为:

riddle(L) :-
    L = [A,B,C,D,E,F,G,H],
    L ins 1..8,
    all_different(L),
    /* horizontal */
    ns(B, E),
    ns(A, C),
    ns(C, F),
    ns(F, H),
    ns(D, G),
    /* vertical */
    ns(B, C),
    ns(C, D),
    ns(E, F),
    ns(F, G),
    /* search solution */
    label(L).

运行它,我得到以下解决方案:

Jekejeke Prolog 3, Runtime Library 1.3.0
(c) 1985-2018, XLOG Technologies GmbH, Switzerland

?- riddle([7,4,1,3,6,8,5,2]).
Yes

?- findall(hit,riddle(_),L), length(L,N), 
   write(N), nl, fail; true.
1656
Yes

编辑31.07.2018:

这留作家庭作业。如果为从左下到右上的对角线以及从 从左上到右下,系统变得更加紧凑,并且仅生成以下四个解决方案:

?- riddle(L).
L = [2,5,8,6,3,1,4,7] ;
L = [2,6,8,5,4,1,3,7] ;
L = [7,3,1,4,5,8,6,2] ;
L = [7,4,1,3,6,8,5,2] ;
No 

答案 1 :(得分:1)

/*
      2,5,
    1,3,6,8
      4,7,
*/

riddle_p(R) :-
    permutation([1,2,3,4,5,6,7,8],R),
    maplist(no_diff_1(R), [[2,5],[1,3,6,8],[4,7],[2,3,4],[5,6,7]]).

no_diff_1(R,[A,B|Is]) :-
    nth1(A,R,X), nth1(B,R,Y), abs(X-Y) > 1,
    !, no_diff_1(R,[B|Is]).
no_diff_1(_,[_]).

在SWI-Prolog中运行,它比clp(fd)解决方案要快得多。