我得到了一个解决方案,实际上这个问题比我之前解决的“SkyScrape & Fences”难题要简单得多。
恐怕我之前误解了问题并发表了错误的评论,建议您放弃已经走的(正确的)道路。
/* 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.
此处编辑是“移植”到 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).