d(2,6)
是一张多米诺骨牌。
我遇到了检查是否有多米诺骨牌列表的问题 通过重新排列列表中的元素以及通过重新组合来成功地连接在一起 交换单个多米诺骨牌。 例如,以下选择有效
?- playout([d(3,6),d(0,4),d(3,4),d(1,3),d(1,6),d(0,1),d(4,4)]).
true.
因为可以安排
[d(1,0),d(0,4),d(4,4),d(4,3),d(3,6),d(6,1),d(1,3)]
但是下面的选择不起作用
?- playout([d(0,3),d(1,2),d(5,6),d(5,5),d(0,2),d(0,5),d(3,5)]).
false.
答案 0 :(得分:2)
这是一个非常有趣的组合任务,超过整数,非常适合Prolog的 CLP(FD)约束。
这是一个解决方案,适用于SICStus Prolog,SWI和YAP下的大多数小修改:
:- use_module(library(clpfd)). dominos_arrangement(Ds, Solution, Vs) :- same_length(Ds, As), dominos_tuples(Ds, Ts), phrase(dominos_ids(As, IDs), Vs), tuples_in(As, Ts), As = [First|Rest], foldl(linked_domino, Rest, First, _), all_distinct(IDs), maplist(domino_triple, Solution, As). linked_domino([Val,Next,_], Prev, [_,Next,_]) :- Prev = [_,Val,_]. dominos_ids([], []) --> []. dominos_ids([[X,Y,ID]|Ds], [ID|IDs]) --> [X,Y,ID], dominos_ids(Ds, IDs). dominos_tuples(Ds, Ts) :- phrase(dominos_tuples_(Ds, 0), Ts). dominos_tuples_([], _) --> []. dominos_tuples_([d(X,Y)|Ds], ID0) --> [[X,Y,ID0],[Y,X,ID0]], { ID #= ID0 + 1 }, dominos_tuples_(Ds, ID). domino_triple(d(X,Y), [X,Y,_]).
使用您的示例,我们已经可以使用最常见的查询来查看核心关系是否按预期终止:
?- Ds = [d(3,6),d(0,4),d(3,4),d(1,3),d(1,6),d(0,1),d(4,4)], dominos_arrangement(Ds, As, Vs). Ds = [d(3, 6), d(0, 4), d(3, 4), d(1, 3), d(1, 6), d(0, 1), d(4, 4)], As = [d(_3398, _3400), d(_3400, _3412), d(_3412, _3424), d(_3424, _3436), d(_3436, _3448), d(_3448, _3460), d(_3460, _3472)], Vs = [_3398, _3400, _3500, _3400, _3412, _3518, _3412, _3424, _3536|...], _3398 in 0..1\/3..4\/6, etc.
是的,这看起来非常好。注意变量别名如何将链链接在一起。
为了制作具体的解决方案,我们在变量列表中使用标记:
?- Ds = [d(3,6),d(0,4),d(3,4),d(1,3),d(1,6),d(0,1),d(4,4)], dominos_arrangement(Ds, As, Vs), label(Vs). Ds = [d(3, 6), d(0, 4), d(3, 4), d(1, 3), d(1, 6), d(0, 1), d(4, 4)], As = [d(1, 0), d(0, 4), d(4, 4), d(4, 3), d(3, 1), d(1, 6), d(6, 3)], Vs = [1, 0, 5, 0, 4, 1, 4, 4, 6|...] ; Ds = [d(3, 6), d(0, 4), d(3, 4), d(1, 3), d(1, 6), d(0, 1), d(4, 4)], As = [d(1, 0), d(0, 4), d(4, 4), d(4, 3), d(3, 6), d(6, 1), d(1, 3)], Vs = [1, 0, 5, 0, 4, 1, 4, 4, 6|...] ; Ds = [d(3, 6), d(0, 4), d(3, 4), d(1, 3), d(1, 6), d(0, 1), d(4, 4)], As = [d(1, 3), d(3, 4), d(4, 4), d(4, 0), d(0, 1), d(1, 6), d(6, 3)], Vs = [1, 3, 3, 3, 4, 2, 4, 4, 6|...] ; Ds = [d(3, 6), d(0, 4), d(3, 4), d(1, 3), d(1, 6), d(0, 1), d(4, 4)], As = [d(1, 3), d(3, 6), d(6, 1), d(1, 0), d(0, 4), d(4, 4), d(4, 3)], Vs = [1, 3, 3, 3, 6, 0, 6, 1, 4|...] ; Ds = [d(3, 6), d(0, 4), d(3, 4), d(1, 3), d(1, 6), d(0, 1), d(4, 4)], As = [d(1, 6), d(6, 3), d(3, 1), d(1, 0), d(0, 4), d(4, 4), d(4, 3)], Vs = [1, 6, 4, 6, 3, 0, 3, 1, 3|...] ; etc.
在回溯时,会生成所有解决方案。
请注意在这种情况下约束求解的通常优势,例如搜索空间的重要修剪,这使得无需详尽地尝试所有组合,并且有可能通过尝试更智能的搜索策略标签选项。