【问题标题】:Second End View puzzle, Prolog [closed]第二端视图谜题,Prolog [关闭]
【发布时间】:2012-10-03 22:11:23
【问题描述】:

我在 swi-prolog 中编写代码来解决数字 1-6 的 Second End View Pazzles 7*7(例如 http://www.funwithpuzzles.com/2009/10/abcd-second-end-view-ev4.html 像这样的 5*5)

:- [library(clpfd)].

gen_row(Ls):-length(Ls, 7), Ls ins 0..6.

abc_view :-

maplist(gen_row, [R1,R2,R3,R4,R5,R6,R7]),
transpose([R1,R2,R3,R4,R5,R6,R7], [C1,C2,C3,C4,C5,C6,C7]),
maplist(all_distinct, [R1,R2,R3,R4,R5,R6,R7]),
maplist(all_distinct, [C1,C2,C3,C4,C5,C6,C7]),

start(R1, 4),
start(R2, 2),
start(R3, 3),
start(R4, 5),
start(R5, 3),
finish(R1, 6),
finish(R2, 4),
finish(R3, 2),
finish(R5, 1),
finish(R7, 2),

start(C2, 3),
start(C3, 4),
start(C4, 3),
start(C5, 5),
start(C6, 4),
start(C7, 1),
finish(C1, 3),
finish(C2, 2),
finish(C3, 5),
finish(C4, 5),
finish(C5, 6),
finish(C6, 1),
finish(C7, 4),

    maplist(writeln, [R1,R2,R3,R4,R5,R6,R7]).

我需要如何编写逻辑来解决它,也许是 4*4 或 5*5.. 我很乐意提供任何帮助。 我需要为 3 次测试编写它,但即使是一次也很重要。

【问题讨论】:

  • 我认为你不能在所有行/列上使用 all_distinct,因为 0(空单元格,不是吗?)可以出现更多次...
  • 我不明白在什么情况下我必须使用 distinct 以及什么对我的任务更好,只能有一个空单元格,是的,这里是 0,每一行和每一列。这是我在大学的第一个也是最后一个实验室,所以我对 prolog 知之甚少。
  • 你是对的。我误解了这个谜题,描述,作为其他人已经指出的(已删除)评论。
  • 我找到了另一个看起来像这样的任务的答案,但我不明白它是完整的代码,因为它在我的 swi-prolog 中不起作用,它总是写错..? - abc_view。错误的。 p.s.对不起我的傻瓜(stackoverflow.com/questions/10686773/end-view-puzzle-prolog
  • 我没有看到已删除的评论。这是关于什么的

标签: prolog logic constraints swi-prolog clpfd


【解决方案1】:

我找到了一个解决方案,实际上这个问题比我解决的“摩天大楼和围栏”难题要简单得多previously

恐怕我之前误解了问题并发表了错误的评论,建议你放弃你已经走的(正确的)道路。

/*  File:    second_end_view_puzzle.pl
    Author:  Carlo,,,
    Created: Oct  8 2012
    Purpose: help to solve Second End View puzzle as quested at
             https://stackoverflow.com/q/12717609/874024
*/


:- [library(clpfd)].

gen_row(Ls) :-
    length(Ls, 7),
    Ls ins 0..6.

abc_view :-

    Rows = [R1,R2,R3,R4,R5,_R6,R7],
    maplist(gen_row, Rows),
    transpose(Rows, [C1,C2,C3,C4,C5,C6,C7]),
    maplist(all_distinct, Rows),
    maplist(all_distinct, [C1,C2,C3,C4,C5,C6,C7]),

    start(R1, 4),
    start(R2, 2),
    start(R3, 3),
    start(R4, 5),
    start(R5, 3),
    finish(R1, 6),
    finish(R2, 4),
    finish(R3, 2),
    finish(R5, 1),
    finish(R7, 2),

    start(C2, 3),
    start(C3, 4),
    start(C4, 3),
    start(C5, 5),
    start(C6, 4),
    start(C7, 1),
    finish(C1, 3),
    finish(C2, 2),
    finish(C3, 5),
    finish(C4, 5),
    finish(C5, 6),
    finish(C6, 1),
    finish(C7, 4),

    maplist(label, Rows),
    maplist(writeln, Rows).

% place the constraint 'SECOND in that direction' using a reified check
start(Vars, Num) :-
    Vars = [A,B,C|_],
    X #<==> ( A #= 0 #\/ B #= 0 ) #/\ C #= Num,
    Y #<==> A #\= 0 #/\ B #= Num,
    X + Y #= 1 .

finish(Vars, Num) :-
    reverse(Vars, Sarv), start(Sarv, Num).

编辑测试:

?- abc_view.
[5,4,0,2,1,6,3]
[6,0,2,3,5,4,1]
[1,3,4,6,2,5,0]
[2,5,1,4,0,3,6]
[0,6,3,5,4,1,2]
[3,2,5,1,6,0,4]
[4,1,6,0,3,2,5]
true ;
false.

edit 这里是“移植”到 GnuProlog。我已经从 SWI-Prolog CLP(FD) 库中复制了 transpose/2 代码。

/*  File:    second_end_view_puzzle.pl
    Author:  Carlo,,,
    Created: Oct  8 2012
    Purpose: help to solve Second End View puzzle as quested at
             https://stackoverflow.com/q/12717609/874024
*/

gen_row(Ls) :-
    length(Ls, 7),
    fd_domain(Ls, 0, 6).

transpose(Ms, Ts) :-
        %must_be(list(list), Ms),
        (   Ms = [] -> Ts = []
        ;   Ms = [F|_],
            transpose(F, Ms, Ts)
        ).

transpose([], _, []).
transpose([_|Rs], Ms, [Ts|Tss]) :-
        lists_firsts_rests(Ms, Ts, Ms1),
        transpose(Rs, Ms1, Tss).

lists_firsts_rests([], [], []).
lists_firsts_rests([[F|Os]|Rest], [F|Fs], [Os|Oss]) :-
        lists_firsts_rests(Rest, Fs, Oss).

writeln(X) :- write(X), nl.

abc_view :-

    Rows = [R1,R2,R3,R4,R5,_R6,R7],
    maplist(gen_row, Rows),
    transpose(Rows, [C1,C2,C3,C4,C5,C6,C7]),
    maplist(fd_all_different, Rows),
    maplist(fd_all_different, [C1,C2,C3,C4,C5,C6,C7]),

    start(R1, 4),
    start(R2, 2),
    start(R3, 3),
    start(R4, 5),
    start(R5, 3),
    finish(R1, 6),
    finish(R2, 4),
    finish(R3, 2),
    finish(R5, 1),
    finish(R7, 2),

    start(C2, 3),
    start(C3, 4),
    start(C4, 3),
    start(C5, 5),
    start(C6, 4),
    start(C7, 1),
    finish(C1, 3),
    finish(C2, 2),
    finish(C3, 5),
    finish(C4, 5),
    finish(C5, 6),
    finish(C6, 1),
    finish(C7, 4),

    maplist(fd_labeling, Rows),
    maplist(writeln, Rows).

% place the constraint 'SECOND in that direction' using a reified check
start(Vars, Num) :-
    Vars = [A,B,C|_],
    X #<=> ( A #= 0 #\/ B #= 0 ) #/\ C #= Num,
    Y #<=> A #\= 0 #/\ B #= Num,
    X + Y #= 1 .

finish(Vars, Num) :-
    reverse(Vars, Sarv), start(Sarv, Num).

【讨论】:

  • 非常感谢您的解决方案。但是要怎么做才能得到不同的答案呢?- abc_view。错误的。?请展示程序如何为您提供结果
  • 查看最新编辑。在调试时,我会先注释掉大部分约束,然后添加一些约束。当约束正常时,这会提供许多解决方案,只需“直观地”检查第一个、第二个等等。然后添加更多,直到覆盖整个集合。
  • 我不明白这一点。请帮助我,一步一步我在做什么。首先,我在 swi-prolog .pl 中创建文件,代码 /* 文件:second_end_view_puzzle.pl 作者:Carlo,,, 创建时间:2012 年 10 月 8 日 目的:帮助解决 stackoverflow.com/q/12717609/874024 */ 要求的 Second End View 难题模块(abc_view,[abc_view/0])。 :- [库(clpfd)]。 gen_row(Ls) :- 长度(Ls, 7), Ls ins 0..6。 ...完成(Vars,Num):-反向(Vars,Sarv),开始(Sarv,Num)。并在主窗口中编译后?-我写“问题”abc_view。
  • 刚刚仔细检查:将程序复制到一个新文件中,编译并运行 abc_view 以获得结果。如果您对效率感兴趣,此查询 ?- time(abc_view). 会导致 % 1,002,499 inferences, 1,343 CPU in 1,349 seconds (100% CPU, 746670 Lips) 但我使用的是低功耗机器和 SWI-Prolog 的调试版本
  • farm9.staticflickr.com/8178/8067194566_a194ea65ec_b.jpg 我正在这样做,我的错误是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多