用序言解决 Str8ts,在设置约束(域)后标记
solve Str8ts with prolog, labeling after set the constraints(domain)
我想用prolog
解决str8ts
我为所有列表设置了 3 个约束:
约束 1: 每个列表 --> all_different(list)
约束 2: 每个列表 --> list ins 1..9
约束 3: 每个列表 --> 白色组之间(或一个黑色之前,或一个黑色之后)2 个黑色字段必须是 无缝
设置约束后,我调用 labeling([ff],PuzzleVariable)
。
问题是设置约束3
让我用我的代码解释一下。
我的代码:
首先我输入包含 81 个元素的列表的拼图(A1、B1、C1 是数字,IB11、IB12... 显示是否为黑色区域) :
puzzle([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19],
[B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29],
[C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39],
[D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49],
[E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59],
[F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69],
[G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79],
[H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89],
[I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]])
之后,我想为列表的每一行和每列设置 3 个约束,所以我为所有行和列调用 "pruefen":
%CHECK ROWS
pruefen([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19]]),
pruefen([[B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29]]),
pruefen([[C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39]]),
pruefen([[D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49]]),
pruefen([[E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59]]),
pruefen([[F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69]]),
pruefen([[G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79]]),
pruefen([[H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89]]),
pruefen([[I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]]),
%CHECK COLUMNS
pruefen([[A1,IB11],[B1,IB21],[C1,IB31], [D1,IB41],[E1,IB51],[F1,IB61],[G1,IB71],[H1,IB81],[I1,IB91]]),
pruefen([[A2,IB12],[B2,IB22],[C2,IB32], [D2,IB42],[E2,IB52],[F2,IB62],[G2,IB72],[H2,IB82],[I2,IB92]]),
pruefen([[A3,IB13],[B3,IB23],[C3,IB33], [D3,IB43],[E3,IB53],[F3,IB63],[G3,IB73],[H3,IB83],[I3,IB93]]),
pruefen([[A4,IB14],[B4,IB24],[C4,IB34], [D4,IB44],[E4,IB54],[F4,IB64],[G4,IB74],[H4,IB84],[I4,IB94]]),
pruefen([[A5,IB15],[B5,IB25],[C5,IB35], [D5,IB45],[E5,IB55],[F5,IB65],[G5,IB75],[H5,IB85],[I5,IB95]]),
pruefen([[A6,IB16],[B6,IB26],[C6,IB36], [D6,IB46],[E6,IB56],[F6,IB66],[G6,IB76],[H6,IB86],[I6,IB96]]),
pruefen([[A7,IB17],[B7,IB27],[C7,IB37], [D7,IB47],[E7,IB57],[F7,IB67],[G7,IB77],[H7,IB87],[I7,IB97]]),
pruefen([[A8,IB18],[B8,IB28],[C8,IB38], [D8,IB48],[E8,IB58],[F8,IB68],[G8,IB78],[H8,IB88],[I8,IB98]]),
pruefen([[A9,IB19],[B9,IB29],[C9,IB39], [D9,IB49],[E9,IB59],[F9,IB69],[G9,IB79],[H9,IB89],[I9,IB99]]),
所以,我为列表调用 pruefen。
首先我排除了所有黑色和未定义的字段,因为我没有need/want为它们设置约束:
%exclude black and undefined lists
exclude(isBlackAndEmpty,L,NewList),
%Constraint 1 and 2, every list ins 1..9 and all different(list)
constraintsFestlegen(NewList),
排除谓词:
isBlackAndEmpty([Variable|IsBlack]):-
IsBlack=:=1,
var(Variable).
设置约束的谓词:
%set constraints for whole list(black and undefined excluded)
variablenListeErstellen([],Variablen):-
%jede Liste darf nur aus Zahlen von 1..9 bestehen
Variablen ins 1..9,
%es dürfen in der Liste keine Zahlen doppelt vorkommen
%bibliothek von SWI-Prolog Bibliothek clpfd
all_different(Variablen).
所以,这是针对约束 1 和 2 的。
约束 3:我将每个列表分成几组白色字段。
创建组的谓词:
%ausstiegspunkt für eine leere liste
listGroupConstraints([]).
%for a list with a black field
listGroupConstraints(List):-
append(Prefix, [[_,1]|Rest],List),
%creates one dimensional list
createOneDimensional(Prefix,OneDimensionalList),
%rekursiv
listGroupConstraints(Rest).
%for a list without a black field
listGroupConstraints(List):-
%convert to one dimensional list
createOneDimensional(List,OneDimensionalList),
%set constraint for one dimensional list
setGroupConstraints(OneDimensionalList).
我用来为所有白色字段组设置约束 3 的 setGroupConstraints。
用于检查无间隙并设置约束 3 的谓词:
%check if group is gapless,
listl(L) :-
[Fst,Lst] ins 1..9,
Fst #=< Lst,
Len #= Lst - Fst + 1,
length(L, Len),
label([Fst,Lst]),
L ins Fst..Lst,
all_different(L).
设置 3 个约束后,我将整个输入列表过滤为仅标记白色字段:
排除(isBlack、List、ExcludedList)
%check if black
isBlack([Variable|IsBlack]):-
IsBlack=:=1.
%create one dimensional list from two dimensional list for labeling all
%get the first variables from list
createOneDimensionalForLabeling([],Variablen):-
print(Variablen),
labeling([ff],Variablen).
createOneDimensionalForLabeling([X|Rest],Variablen):-
listeInListe(X,Variable,IsBlack),
append(Variablen,[Variable],MyList),
createOneDimensionalForLabeling(Rest,MyList).
但是在标记时我得到:错误:参数没有充分实例化
有人知道这个问题吗?
示例输入:
puzzle([[9,1],[6,0],[8,0],[1,0],[_,0],[_,0],[_,0],[4,0],[_,0],[_,0],[_,0],[_,1],[_,1],[4,0],[_,0],[_,0],[7,1],[_,1],[5,0],[_,1],[_,1],[_,0],[3,0],[_,0],[_,1],[_,1],[_,0],[_,0],[_,1],[_,0],[_,0],[_,0],[4,0],[6,1],[_,0],[_,0],[_,1],[_,0],[_,0],[_,0],[_,1],[_,0],[_,0],[_,0],[_,1],[3,0],[_,0],[_,1],[_,0],[5,0],[8,0],[_,0],[_,1],[_,0],[_,0],[_,1],[_,1],[_,0],[_,0],[_,0],[_,1],[5,1],[_,0],[_,1],[_,1],[5,0],[_,0],[_,0],[_,1],[4,1],[1,0],[_,0],[_,0],[7,0],[_,0],[_,0],[_,0],[_,0],[_,0],[_,0],[1,1]]).
已编辑
我可以从变量中删除域吗?
当我从二维列表中创建一维列表时。在调用 i 时,变量列表有一个域:lists:append([6, 8, 1, _G5{clpfd = ...}, _G6{clpfd = ...}, _G7{clpfd = ...}, 4|...],
但是完成一维列表后,变量看起来像:
[6,8,1,_G5,_G6,_G7,4,_G8,_G9,_G10,4,...]
编辑 2
如果我打电话给constraintsFestlegen([[A,0],[B,0],[4,0],[C,0],[D,0],[7,1]]),listl([A,B]),listl([4,C,D]),labeling([ff],[A,B,C,D]).
它工作正常。但是当我打电话给 pruefen([[A,0],[1,1],[B,0],[3,0],[_,1],[6,0],[C,0],[D,0],[E,0]]),labeling([ff],[A,B,C,D,E]).
我运行出栈了。所以如果我是对的,错误必须在过滤列表中......
我在看str8ts拼图。这个谜题的难点在于编码一个事实,即有一组连续的数字,但不是有序的!
解决任务的一种方法是对集合进行排序,并说当Len是列表的长度时,列表的第一个和最后一个数字之间的差是Len-1。
集合中的所有数字都统一时,这很容易做到,但是当它们不统一时,我们该怎么办?
您可以 post 在 Prolog 中使用 when/2 约束:
所以你可以说当Seq的所有数字统一时,(例如在Prolog中:ground(Seq)),你会按照我上面解释的去做。
在序言中你将写:
when(ground(Seq),
( sort(Seq, SSeq),
reverse(SSeq, RSeq),
SSEq = [F|_],
RSeq = [L | _],
L - F =:= Len - 1)))
编辑:我的解决方案
:- use_module(library(clpfd)).
:- use_module(library(lambda)).
str8ts(N) :-
grille(N, Tableau),
set_lines(Tableau, Vs1),
clpfd:transpose(Tableau, R_T),
set_lines(R_T, Vs2),
flatten([Vs1, Vs2], Vs),
label(Vs),
maplist(writeln, Tableau).
set_lines(Tableau, Vs) :-
maplist(set_one_line, Tableau, Vs).
set_one_line(Ligne, Vs) :-
% we fetch forbidden numbers
foldl(\X^Y^Z^((nonvar(X), X < 0)
-> Z = [X | Y]
; Z = Y), Ligne, [], Interdites),
set_one_line(Ligne, Interdites, [], [], Vs).
% @arg1 : line to study
% @arg2 : list of forbidden numbers for this line
% @arg3 : sequence of variables to unify
% @arg4 : Sequences allready seen
% @arg5 : final list of variables
% Line finished,
% all the numbers of the line must be different
set_one_line([],Forbidden, Tmp_Vs, Cur_Vs, Vs) :-
flatten( [Tmp_Vs | Cur_Vs], Vs),
all_distinct(Vs),
init_sequence(Tmp_Vs,Forbidden).
set_one_line([H|T],Forbidden, Tmp_Vs, Cur_Vs, Vs) :-
% nonvar must be tested because during backtrack
% we may have error message :
% ERROR: H > 0 : Arguments are not sufficiently instantiated
( var(H); nonvar(H), H > 0),
set_one_line(T, Forbidden, [H | Tmp_Vs], Cur_Vs, Vs).
set_one_line([H|T],Forbidden, Tmp_Vs, Cur_Vs, Vs) :-
nonvar(H),
H =< 0,
% here we must init a sequence
init_sequence(Tmp_Vs,Forbidden),
set_one_line(T, Forbidden, [], [Tmp_Vs |Cur_Vs], Vs).
% the sequence may be empty
init_sequence([], _).
% the sequence may have only one element
init_sequence([X], Forbidden) :-
maplist(\Y^(X #\= -Y), Forbidden).
init_sequence(L, Forbidden) :-
set_constraint(L),
maplist(L +\X^maplist(X +\Y^(Y #\= -X), L), Forbidden).
set_constraint(Line) :-
length(Line, Len),
Line ins 1..9,
all_distinct(Line),
% we post a contraint on the set of elements
when(ground(Line),
( sort(Line, [H | Tail]),
reverse([H | Tail], [K |_]),
K - H =:= Len-1)).
% 142,019,193 inferences, 17.394 CPU in 17.441 seconds (100% CPU, 8164786 Lips)
grille(1,[[0,0,_,_,5,_,_,-3,0],
[_,6,_,_,0,0,1,_,_],
[_,_,_,0,-8,_,_,_,_],
[9,_,_,-4,_,_,_,0,-5],
[0,_,_,_,_,3,_,_,0],
[0,0,_,_,_,-9,_,4,_],
[4,_,3,_,0,0,_,6,_],
[_,_,1,0,0,_,_,_,_],
[0,0,8,_,_,_,_,0,-2]]).
% 37,023,520 inferences, 3.900 CPU in 3.916 seconds (100% CPU, 9493149 Lips)
grille(2, [[0,-1,_,_,_,0,_,8,6],
[_,4,_,_,8,7,_,_,0],
[_,_,_,0,_,_,_,_,0],
[0,0,3,_,_,-8,0,_,_],
[_,_,_,_,1,_,_,_,_],
[6,_,0,-4,_,_,_,-9,0],
[-2,_,_,_,9,0,_,_,_],
[0,_,_,_,_,_,6,_,_],
[_,_,_,0,_,_,_,0,-3]]).
我想用prolog
解决str8ts我为所有列表设置了 3 个约束:
约束 1: 每个列表 -->
all_different(list)
约束 2: 每个列表 -->
list ins 1..9
约束 3: 每个列表 --> 白色组之间(或一个黑色之前,或一个黑色之后)2 个黑色字段必须是 无缝
设置约束后,我调用 labeling([ff],PuzzleVariable)
。
问题是设置约束3 让我用我的代码解释一下。 我的代码:
首先我输入包含 81 个元素的列表的拼图(A1、B1、C1 是数字,IB11、IB12... 显示是否为黑色区域) :
puzzle([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19],
[B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29],
[C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39],
[D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49],
[E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59],
[F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69],
[G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79],
[H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89],
[I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]])
之后,我想为列表的每一行和每列设置 3 个约束,所以我为所有行和列调用 "pruefen":
%CHECK ROWS
pruefen([[A1,IB11],[A2,IB12],[A3,IB13], [A4,IB14],[A5,IB15],[A6,IB16],[A7,IB17],[A8,IB18],[A9,IB19]]),
pruefen([[B1,IB21],[B2,IB22],[B3,IB23], [B4,IB24],[B5,IB25],[B6,IB26],[B7,IB27],[B8,IB28],[B9,IB29]]),
pruefen([[C1,IB31],[C2,IB32],[C3,IB33], [C4,IB34],[C5,IB35],[C6,IB36],[C7,IB37],[C8,IB38],[C9,IB39]]),
pruefen([[D1,IB41],[D2,IB42],[D3,IB43], [D4,IB44],[D5,IB45],[D6,IB46],[D7,IB47],[D8,IB48],[D9,IB49]]),
pruefen([[E1,IB51],[E2,IB52],[E3,IB53], [E4,IB54],[E5,IB55],[E6,IB56],[E7,IB57],[E8,IB58],[E9,IB59]]),
pruefen([[F1,IB61],[F2,IB62],[F3,IB63], [F4,IB64],[F5,IB65],[F6,IB66],[F7,IB67],[F8,IB68],[F9,IB69]]),
pruefen([[G1,IB71],[G2,IB72],[G3,IB73], [G4,IB74],[G5,IB75],[G6,IB76],[G7,IB77],[G8,IB78],[G9,IB79]]),
pruefen([[H1,IB81],[H2,IB82],[H3,IB83], [H4,IB84],[H5,IB85],[H6,IB86],[H7,IB87],[H8,IB88],[H9,IB89]]),
pruefen([[I1,IB91],[I2,IB92],[I3,IB93], [I4,IB94],[I5,IB95],[I6,IB96],[I7,IB97],[I8,IB98],[I9,IB99]]),
%CHECK COLUMNS
pruefen([[A1,IB11],[B1,IB21],[C1,IB31], [D1,IB41],[E1,IB51],[F1,IB61],[G1,IB71],[H1,IB81],[I1,IB91]]),
pruefen([[A2,IB12],[B2,IB22],[C2,IB32], [D2,IB42],[E2,IB52],[F2,IB62],[G2,IB72],[H2,IB82],[I2,IB92]]),
pruefen([[A3,IB13],[B3,IB23],[C3,IB33], [D3,IB43],[E3,IB53],[F3,IB63],[G3,IB73],[H3,IB83],[I3,IB93]]),
pruefen([[A4,IB14],[B4,IB24],[C4,IB34], [D4,IB44],[E4,IB54],[F4,IB64],[G4,IB74],[H4,IB84],[I4,IB94]]),
pruefen([[A5,IB15],[B5,IB25],[C5,IB35], [D5,IB45],[E5,IB55],[F5,IB65],[G5,IB75],[H5,IB85],[I5,IB95]]),
pruefen([[A6,IB16],[B6,IB26],[C6,IB36], [D6,IB46],[E6,IB56],[F6,IB66],[G6,IB76],[H6,IB86],[I6,IB96]]),
pruefen([[A7,IB17],[B7,IB27],[C7,IB37], [D7,IB47],[E7,IB57],[F7,IB67],[G7,IB77],[H7,IB87],[I7,IB97]]),
pruefen([[A8,IB18],[B8,IB28],[C8,IB38], [D8,IB48],[E8,IB58],[F8,IB68],[G8,IB78],[H8,IB88],[I8,IB98]]),
pruefen([[A9,IB19],[B9,IB29],[C9,IB39], [D9,IB49],[E9,IB59],[F9,IB69],[G9,IB79],[H9,IB89],[I9,IB99]]),
所以,我为列表调用 pruefen。
首先我排除了所有黑色和未定义的字段,因为我没有need/want为它们设置约束:
%exclude black and undefined lists
exclude(isBlackAndEmpty,L,NewList),
%Constraint 1 and 2, every list ins 1..9 and all different(list)
constraintsFestlegen(NewList),
排除谓词:
isBlackAndEmpty([Variable|IsBlack]):-
IsBlack=:=1,
var(Variable).
设置约束的谓词:
%set constraints for whole list(black and undefined excluded)
variablenListeErstellen([],Variablen):-
%jede Liste darf nur aus Zahlen von 1..9 bestehen
Variablen ins 1..9,
%es dürfen in der Liste keine Zahlen doppelt vorkommen
%bibliothek von SWI-Prolog Bibliothek clpfd
all_different(Variablen).
所以,这是针对约束 1 和 2 的。
约束 3:我将每个列表分成几组白色字段。
创建组的谓词:
%ausstiegspunkt für eine leere liste
listGroupConstraints([]).
%for a list with a black field
listGroupConstraints(List):-
append(Prefix, [[_,1]|Rest],List),
%creates one dimensional list
createOneDimensional(Prefix,OneDimensionalList),
%rekursiv
listGroupConstraints(Rest).
%for a list without a black field
listGroupConstraints(List):-
%convert to one dimensional list
createOneDimensional(List,OneDimensionalList),
%set constraint for one dimensional list
setGroupConstraints(OneDimensionalList).
我用来为所有白色字段组设置约束 3 的 setGroupConstraints。
用于检查无间隙并设置约束 3 的谓词:
%check if group is gapless,
listl(L) :-
[Fst,Lst] ins 1..9,
Fst #=< Lst,
Len #= Lst - Fst + 1,
length(L, Len),
label([Fst,Lst]),
L ins Fst..Lst,
all_different(L).
设置 3 个约束后,我将整个输入列表过滤为仅标记白色字段:
排除(isBlack、List、ExcludedList)
%check if black
isBlack([Variable|IsBlack]):-
IsBlack=:=1.
%create one dimensional list from two dimensional list for labeling all
%get the first variables from list
createOneDimensionalForLabeling([],Variablen):-
print(Variablen),
labeling([ff],Variablen).
createOneDimensionalForLabeling([X|Rest],Variablen):-
listeInListe(X,Variable,IsBlack),
append(Variablen,[Variable],MyList),
createOneDimensionalForLabeling(Rest,MyList).
但是在标记时我得到:错误:参数没有充分实例化
有人知道这个问题吗?
示例输入:
puzzle([[9,1],[6,0],[8,0],[1,0],[_,0],[_,0],[_,0],[4,0],[_,0],[_,0],[_,0],[_,1],[_,1],[4,0],[_,0],[_,0],[7,1],[_,1],[5,0],[_,1],[_,1],[_,0],[3,0],[_,0],[_,1],[_,1],[_,0],[_,0],[_,1],[_,0],[_,0],[_,0],[4,0],[6,1],[_,0],[_,0],[_,1],[_,0],[_,0],[_,0],[_,1],[_,0],[_,0],[_,0],[_,1],[3,0],[_,0],[_,1],[_,0],[5,0],[8,0],[_,0],[_,1],[_,0],[_,0],[_,1],[_,1],[_,0],[_,0],[_,0],[_,1],[5,1],[_,0],[_,1],[_,1],[5,0],[_,0],[_,0],[_,1],[4,1],[1,0],[_,0],[_,0],[7,0],[_,0],[_,0],[_,0],[_,0],[_,0],[_,0],[1,1]]).
已编辑
我可以从变量中删除域吗?
当我从二维列表中创建一维列表时。在调用 i 时,变量列表有一个域:lists:append([6, 8, 1, _G5{clpfd = ...}, _G6{clpfd = ...}, _G7{clpfd = ...}, 4|...],
但是完成一维列表后,变量看起来像:
[6,8,1,_G5,_G6,_G7,4,_G8,_G9,_G10,4,...]
编辑 2
如果我打电话给constraintsFestlegen([[A,0],[B,0],[4,0],[C,0],[D,0],[7,1]]),listl([A,B]),listl([4,C,D]),labeling([ff],[A,B,C,D]).
它工作正常。但是当我打电话给 pruefen([[A,0],[1,1],[B,0],[3,0],[_,1],[6,0],[C,0],[D,0],[E,0]]),labeling([ff],[A,B,C,D,E]).
我运行出栈了。所以如果我是对的,错误必须在过滤列表中......
我在看str8ts拼图。这个谜题的难点在于编码一个事实,即有一组连续的数字,但不是有序的! 解决任务的一种方法是对集合进行排序,并说当Len是列表的长度时,列表的第一个和最后一个数字之间的差是Len-1。
集合中的所有数字都统一时,这很容易做到,但是当它们不统一时,我们该怎么办?
您可以 post 在 Prolog 中使用 when/2 约束:
所以你可以说当Seq的所有数字统一时,(例如在Prolog中:ground(Seq)),你会按照我上面解释的去做。
在序言中你将写:
when(ground(Seq),
( sort(Seq, SSeq),
reverse(SSeq, RSeq),
SSEq = [F|_],
RSeq = [L | _],
L - F =:= Len - 1)))
编辑:我的解决方案
:- use_module(library(clpfd)).
:- use_module(library(lambda)).
str8ts(N) :-
grille(N, Tableau),
set_lines(Tableau, Vs1),
clpfd:transpose(Tableau, R_T),
set_lines(R_T, Vs2),
flatten([Vs1, Vs2], Vs),
label(Vs),
maplist(writeln, Tableau).
set_lines(Tableau, Vs) :-
maplist(set_one_line, Tableau, Vs).
set_one_line(Ligne, Vs) :-
% we fetch forbidden numbers
foldl(\X^Y^Z^((nonvar(X), X < 0)
-> Z = [X | Y]
; Z = Y), Ligne, [], Interdites),
set_one_line(Ligne, Interdites, [], [], Vs).
% @arg1 : line to study
% @arg2 : list of forbidden numbers for this line
% @arg3 : sequence of variables to unify
% @arg4 : Sequences allready seen
% @arg5 : final list of variables
% Line finished,
% all the numbers of the line must be different
set_one_line([],Forbidden, Tmp_Vs, Cur_Vs, Vs) :-
flatten( [Tmp_Vs | Cur_Vs], Vs),
all_distinct(Vs),
init_sequence(Tmp_Vs,Forbidden).
set_one_line([H|T],Forbidden, Tmp_Vs, Cur_Vs, Vs) :-
% nonvar must be tested because during backtrack
% we may have error message :
% ERROR: H > 0 : Arguments are not sufficiently instantiated
( var(H); nonvar(H), H > 0),
set_one_line(T, Forbidden, [H | Tmp_Vs], Cur_Vs, Vs).
set_one_line([H|T],Forbidden, Tmp_Vs, Cur_Vs, Vs) :-
nonvar(H),
H =< 0,
% here we must init a sequence
init_sequence(Tmp_Vs,Forbidden),
set_one_line(T, Forbidden, [], [Tmp_Vs |Cur_Vs], Vs).
% the sequence may be empty
init_sequence([], _).
% the sequence may have only one element
init_sequence([X], Forbidden) :-
maplist(\Y^(X #\= -Y), Forbidden).
init_sequence(L, Forbidden) :-
set_constraint(L),
maplist(L +\X^maplist(X +\Y^(Y #\= -X), L), Forbidden).
set_constraint(Line) :-
length(Line, Len),
Line ins 1..9,
all_distinct(Line),
% we post a contraint on the set of elements
when(ground(Line),
( sort(Line, [H | Tail]),
reverse([H | Tail], [K |_]),
K - H =:= Len-1)).
% 142,019,193 inferences, 17.394 CPU in 17.441 seconds (100% CPU, 8164786 Lips)
grille(1,[[0,0,_,_,5,_,_,-3,0],
[_,6,_,_,0,0,1,_,_],
[_,_,_,0,-8,_,_,_,_],
[9,_,_,-4,_,_,_,0,-5],
[0,_,_,_,_,3,_,_,0],
[0,0,_,_,_,-9,_,4,_],
[4,_,3,_,0,0,_,6,_],
[_,_,1,0,0,_,_,_,_],
[0,0,8,_,_,_,_,0,-2]]).
% 37,023,520 inferences, 3.900 CPU in 3.916 seconds (100% CPU, 9493149 Lips)
grille(2, [[0,-1,_,_,_,0,_,8,6],
[_,4,_,_,8,7,_,_,0],
[_,_,_,0,_,_,_,_,0],
[0,0,3,_,_,-8,0,_,_],
[_,_,_,_,1,_,_,_,_],
[6,_,0,-4,_,_,_,-9,0],
[-2,_,_,_,9,0,_,_,_],
[0,_,_,_,_,_,6,_,_],
[_,_,_,0,_,_,_,0,-3]]).