Prolog 从最短到最长对列表进行排序

Prolog 从最短到最长对列表进行排序,prolog,combinatorics,prolog-findall,Prolog,Combinatorics,Prolog Findall,我最近学习了prolog,正在尝试制作一个程序,为著名的谜题骑士之旅找到解决方案 [在这里找到] 使用Warnsdorff算法,我试图从棋盘上的某个特定位置找到所有可能的移动,然后做出可能移动最少的移动,然后重复这个过程,但是我很难找到所说的移动 这是到目前为止我的代码 possibleKnightMove(I, J, I1, J1) :- I1 is I+1, J1 is J+2. possibleKnightMove(I, J, I1, J1) :- I1 is I+2, J1 is J+1

我最近学习了prolog,正在尝试制作一个程序,为著名的谜题骑士之旅找到解决方案 [在这里找到]

使用Warnsdorff算法,我试图从棋盘上的某个特定位置找到所有可能的移动,然后做出可能移动最少的移动,然后重复这个过程,但是我很难找到所说的移动

这是到目前为止我的代码

possibleKnightMove(I, J, I1, J1) :- I1 is I+1, J1 is J+2.
possibleKnightMove(I, J, I1, J1) :- I1 is I+2, J1 is J+1.
possibleKnightMove(I, J, I1, J1) :- I1 is I+2, J1 is J-1.
possibleKnightMove(I, J, I1, J1) :- I1 is I+1, J1 is J-2.
possibleKnightMove(I, J, I1, J1) :- I1 is I-1, J1 is J-2.
possibleKnightMove(I, J, I1, J1) :- I1 is I-2, J1 is J+1.
possibleKnightMove(I, J, I1, J1) :- I1 is I-2, J1 is J-1.
possibleKnightMove(I, J, I1, J1) :- I1 is I-1, J1 is J+2.

possible_knight_moves(Rows, Columns, X, Y, Visited, NewX, NewY) :-
    possibleKnightMove(X, Y, NewX, NewY),
    NewX > 0, NewX =< Rows,
    NewY > 0, NewY =< Columns,
    \+ member([NewX,NewY], Visited).

possible_moves_count(Rows, Columns, X, Y, Visited, Count) :-
    findall(_, possible_knight_moves(Rows, Columns, X, Y, Visited, _NewX, _NewY), Moves),
    length(Moves, Count).

warnsdorff(Rows, Columns, X, Y, Visited, NewX, NewY, Score) :-
    possible_knight_moves(Rows, Columns, X, Y, Visited, NewX, NewY),
    possible_moves_count(Rows, Columns, NewX, NewY, [[NewX, NewY] | Visited], Score).
结果应该是

NewX = 4,
NewY = 7,
Score = 5
不管我得到什么

NewX = 1,
NewY = 4,
Score = 3

如果有人能帮助我以最低分数获得
NewX
NewY
,那就太好了

一个好的解决方案是将所有可能的移动表示为
N点
其中(例如):

  • N
    是仍然可以从
    Spot
  • Spot
    是我们可以搬到的地方
在这样的列表中,可以使用
keysort/2
对列表进行排序,以使对中的第一个元素按非降序排列。例如,此列表的第一个元素将是在进一步移动方面最受限制的点

您已经非常接近解决方案。我建议您首先集中精力评估单个可能的移动,使用类似于
spot\u freedom(S,F)
的谓词,计算spot
S
的自由度
F
(计算从
S
仍然可能的移动次数)

然后,您可以简单地执行以下操作:

findall(F-S, spot_freedom(S, F), SFs0),
keysort(SFs0, SFs)
并在SFs中拥有候选点的关键排序列表。然后,您可以选择(例如)此列表的第一个元素,或使用:

member(_-Target, SFs)
以增加回溯自由度的顺序尝试可用点


请注意,
spot\u freedom
可能需要额外的参数,例如已进行移动的历史记录,以检测哪些点已被占用。我把这件事留作练习。

您输入了什么查询?对不起,我忘了提及这一点,我将编辑我的问题您认为您的代码的哪一部分将强制执行
分数
最低?另外,我不确定您显示的代码是否是您运行的代码。您显示的结果会导致该查询的实例化错误。我记得阅读findall会对结果列表进行排序,它存储符合目标的所有元素,但如果不是这样,我不确定如何自己解决这个问题。是的,这是我的意图,我的查询实际上意味着如果我在(3,5)上空间巫师从这个空间所有可能移动中的一个,如果移动的话,可能会有最少的移动,所以空变量实际上每一个都代表一个可以从这个可能移动中移动的移动,我想得到的是x,y,它会使这些空变量的数量最少谢谢,我没有想到使用pairs,主要是因为我对prolog还不熟悉,不知道它们的存在,我会尝试你的建议,并让你知道它是否有效。
member(_-Target, SFs)