为了好玩,我一直试图使用Warnsdorf的规则在gprolog中编写一个Knight's Tour(https://en.wikipedia.org/wiki/Knight%27s_tour)求解器。
我发现另一篇关于效率的SO帖子提供了B-prolog的解决方案: knight's tour efficient solution
我的问题出现在以下部分:
div {
display: flex;
width: 100%;
height: 100%
}
.flex-child-container {
flex-direction: column;
}
B-prolog以tabled谓词为特色,而gprolog则没有。我在尝试将表格部分翻译成gprolog时遇到了很大的困难。在实践中,该函数应该从当前位置返回移动,从而导致最少次数可能从新位置移动(连接是随机选择的)。
非常感谢任何帮助。干杯!
答案 0 :(得分:1)
对于这个问题,表格可能有点过分。由于Visits
列表已在解决时继续使用,因此只需使用memberchk / 2。我在SWI-Prolog中获得了这个解决方案(其中,BTW,表格已实施,但无法使用您链接的原始编码解决难题):
?- time(knight(8, 8, 1, 1, [], Path))...
% 19,973 inferences, 0.019 CPU in 0.019 seconds (100% CPU, 1047591 Lips)
[(1,1),(2,3),(1,5),(2,7),(4,8),(6,7),(8,8),(7,6),(6,8),(8,7),(7,5),(8,3),(7,1),(5,2),(3,1),(1,2),(2,4),(1,6),(2,8),(3,6),(1,7),(3,8),(5,7),(7,8),(8,6),(7,4),(8,2),(6,1),(4,2),(2,1),(1,3),(3,2),(5,1),(6,3),(8,4),(7,2),(5,3),(4,1),(2,2),(1,4),(3,3),(2,5),(4,4),(6,5),(4,6),(3,4),(5,5),(4,3),(6,2),(8,1),(7,3),(5,4),(3,5),(4,7),(2,6),(1,8),(3,7),(4,5),(6,4),(5,6),(7,7),(5,8),(6,6),(8,5)]
如果你愿意,我可以告诉你Warnsdorff规则。我已使用setof / 3来获取最低计数,加入possible_knight_moves/7
和possible_moves_count/6
。
修改强>
根据要求:
warnsdorff(R, C, X, Y, Visits, NewX_, NewY_) :-
setof((Count, NewX, NewY), (
possible_knight_moves(R, C, X, Y, Visits, NewX, NewY),
possible_moves_count(R, C, NewX, NewY, [(NewX, NewY) | Visits], Count)
), [(_, NewX_, NewY_)|_]).
为清楚起见,我已将输出变量NewX_,NewY_重命名,但这无关紧要 - 它也适用于原始命名。