免责声明:矩阵表示为列表,其中数字是行,索引(1-8)是列号。
我是Prolog的新手,并根据以下指南尝试解决以下问题:
我的代码:
eightQueens(Board) :-
permutation([1,2,3,4,5,6,7,8], Board),
checkDiagonals(Board).
/* Check Diagonal and AntiDiagonal (Diagonal not implemented yet)
checkD checks antidiagonal */
checkDiagonals([H|T]) :-
checkD([H|T]).
/* Value is the index of H so it acts as the column value.
dValue is the sum of H, which represents row value, and Value.
If any two queens have the same dValue this means they are in
the same anti-diagonal.
checkD gets the dValue of the first element in the list and
passes it to checkDHelper which compares the dValue against
the dValue's of the other elements in the list. */
checkD([]).
checkD([H|T]) :-
indexOf([H|T], H, RowValue),
findValue(RowValue, H, DValue),
checkDHelper(T, DValue),
checkD(T).
/* checkDHelper compares the dValue against
the dValue's of the other elements in the list. */
checkDHelper([], DValue).
checkDHelper([H|T], DValue) :-
indexOf([H|T], H, RowValueIndex),
findValue(IndexValue, H, DValueIndex),
%check if dValue of current index is equal to Value provided
notEqual(DValue, DValueIndex),
checkDHelper(T, DValue).
%Finds index of the element
indexOf([Element|_], Element, 1).
indexOf([_|Tail], Element, Value) :-
indexOf(Tail, Element, Value1),
Value is Value1 + 1.
%Checks if values are not equal
notEqual(X, Y) :-
X =\= Y.
%Finds dValue
findValue(RowValue, ColumnValue, dValue) :-
dValue is X + Y.
下面是一个可以正常工作的板的示例(表示为checkDiagonals([5,1,8,4,2,7,3,6])。)
答案 0 :(得分:1)
这摘自Ivan Bratko(WorldCat)的Prolog Programming for Artificial Intelligence
第四版
第111页-图4.12八皇后问题的程序2。
solution(Queens) :-
permutation([1,2,3,4,5,6,7,8], Queens),
safe(Queens).
% safe(Queens): Queens is a list of Y-coordinates of non-attacking queens
safe([]).
safe([Queen|Others]) :-
safe(Others),
noattack(Queen,Others,1).
% noattack(Queen, Queens, Dist):
% Queen does not attack any queen in Queens at horizontal distance Dist
noattack(_,[],_).
noattack(Y,[Y1|Ylist],Xdist) :-
Y1 - Y =\= Xdist, % Not upward diagonal attack
Y - Y1 =\= Xdist, % Not downward diagonal attack
Dist1 is Xdist + 1,
noattack(Y,Ylist,Dist1).
示例运行。
solution(Queens).
Queens = [1, 5, 8, 6, 3, 7, 2, 4] ;
Queens = [1, 6, 8, 3, 7, 4, 2, 5] ;
Queens = [1, 7, 4, 6, 8, 2, 5, 3] ;
Queens = [1, 7, 5, 8, 2, 4, 6, 3] ;
Queens = [2, 4, 6, 8, 3, 1, 7, 5] ;
Queens = [2, 5, 7, 1, 3, 8, 6, 4] ;
Queens = [2, 5, 7, 4, 1, 8, 6, 3] ;
Queens = [2, 6, 1, 7, 4, 8, 3, 5] ;
Queens = [2, 6, 8, 3, 1, 4, 7, 5] ;
Queens = [2, 7, 3, 6, 8, 5, 1, 4] ;
Queens = [2, 7, 5, 8, 1, 4, 6, 3] ;
Queens = [2, 8, 6, 1, 3, 5, 7, 4] ;
Queens = [3, 1, 7, 5, 8, 2, 4, 6] ;
Queens = [3, 5, 2, 8, 1, 7, 4, 6] ;
Queens = [3, 5, 2, 8, 6, 4, 7, 1] ;
Queens = [3, 5, 7, 1, 4, 2, 8, 6] ;
Queens = [3, 5, 8, 4, 1, 7, 2, 6] ;
Queens = [3, 6, 2, 5, 8, 1, 7, 4]
Action (h for help) ? abort
如果您知道如何refactor Prolog代码,然后更改谓词名称和变量名称,并旋转木板,使行为列,列为行,则此代码可能与您的代码看起来不同,您将看到此答案与您的想法和代码相同。
这是答案的第二部分。
solution_2(N,Queens) :-
numlist(1,N,List),
permutation(List, Queens),
safe(Queens).
示例运行。
?- solution_2(1,Queens).
Queens = [1] ;
false.
?- solution_2(2,Queens).
false.
?- solution_2(3,Queens).
false.
?- solution_2(4,Queens).
Queens = [2, 4, 1, 3] ;
Queens = [3, 1, 4, 2] ;
false.
?- solution_2(5,Queens).
Queens = [1, 3, 5, 2, 4] ;
Queens = [1, 4, 2, 5, 3] ;
Queens = [2, 4, 1, 3, 5] ;
Queens = [2, 5, 3, 1, 4] ;
Queens = [3, 1, 4, 2, 5] ;
Queens = [3, 5, 2, 4, 1] ;
Queens = [4, 1, 3, 5, 2] ;
Queens = [4, 2, 5, 3, 1] ;
Queens = [5, 2, 4, 1, 3] ;
Queens = [5, 3, 1, 4, 2] ;
false.
?- solution_2(6,Queens).
Queens = [2, 4, 6, 1, 3, 5] ;
Queens = [3, 6, 2, 5, 1, 4] ;
Queens = [4, 1, 5, 2, 6, 3] ;
Queens = [5, 3, 1, 6, 4, 2] ;
false.
?- solution_2(7,Queens).
Queens = [1, 3, 5, 7, 2, 4, 6] ;
Queens = [1, 4, 7, 3, 6, 2, 5] ;
Queens = [1, 5, 2, 6, 3, 7, 4] ;
Queens = [1, 6, 4, 2, 7, 5, 3] ;
Queens = [2, 4, 1, 7, 5, 3, 6] ;
Queens = [2, 4, 6, 1, 3, 5, 7] ;
Queens = [2, 5, 1, 4, 7, 3, 6] ;
Queens = [2, 5, 3, 1, 7, 4, 6] ;
Queens = [2, 5, 7, 4, 1, 3, 6] ;
Queens = [2, 6, 3, 7, 4, 1, 5] ;
Queens = [2, 7, 5, 3, 1, 6, 4] ;
Queens = [3, 1, 6, 2, 5, 7, 4] ;
Queens = [3, 1, 6, 4, 2, 7, 5] ;
Queens = [3, 5, 7, 2, 4, 6, 1] ;
Queens = [3, 6, 2, 5, 1, 4, 7] ;
Queens = [3, 7, 2, 4, 6, 1, 5] ;
Queens = [3, 7, 4, 1, 5, 2, 6] ;
Queens = [4, 1, 3, 6, 2, 7, 5] ;
Queens = [4, 1, 5, 2, 6, 3, 7] ;
Queens = [4, 2, 7, 5, 3, 1, 6] ;
Queens = [4, 6, 1, 3, 5, 7, 2] ;
Queens = [4, 7, 3, 6, 2, 5, 1] ;
Queens = [4, 7, 5, 2, 6, 1, 3] ;
Queens = [5, 1, 4, 7, 3, 6, 2] ;
Queens = [5, 1, 6, 4, 2, 7, 3] ;
Queens = [5, 2, 6, 3, 7, 4, 1] ;
Queens = [5, 3, 1, 6, 4, 2, 7] ;
Queens = [5, 7, 2, 4, 6, 1, 3] ;
Queens = [5, 7, 2, 6, 3, 1, 4] ;
Queens = [6, 1, 3, 5, 7, 2, 4] ;
Queens = [6, 2, 5, 1, 4, 7, 3] ;
Queens = [6, 3, 1, 4, 7, 5, 2] ;
Queens = [6, 3, 5, 7, 1, 4, 2] ;
Queens = [6, 3, 7, 4, 1, 5, 2] ;
Queens = [6, 4, 2, 7, 5, 3, 1] ;
Queens = [6, 4, 7, 1, 3, 5, 2] ;
Queens = [7, 2, 4, 6, 1, 3, 5] ;
Queens = [7, 3, 6, 2, 5, 1, 4] ;
Queens = [7, 4, 1, 5, 2, 6, 3] ;
Queens = [7, 5, 3, 1, 6, 4, 2] ;
false.
编辑
来自评论The logic Bratko is using does not make sense to me.
如果代码没有意义,请尝试执行此操作。将对谓词的调用隐藏到write语句中,以查看Prolog向谓词提供的值。然后,有时它比有时使用trace有意义,并且更小,更快。
solution_3(N,Queens) :-
numlist(1,N,List),
permutation(List, Queens),
safe_3(Queens).
safe_3([]).
safe_3([Queen|Others]) :-
safe_3(Others),
noattack_3(Queen,Others,1).
noattack_3(_,[],_).
noattack_3(Y,[Y1|Ylist],Xdist) :-
write('noattack_3 - Y:'),write(Y),write(', Y1: '),write(Y1),write(', Ylist: '),write(Ylist),write(', Xdist: '),writeln(Xdist),
Dist1 is Xdist + 1,
noattack_3(Y,Ylist,Dist1).
以3x3的木板运行可以得到:
?- solution_3(3,Queens).
noattack_3 - Y:2, Y1: 3, Ylist: [], Xdist: 1
noattack_3 - Y:1, Y1: 2, Ylist: [3], Xdist: 1
noattack_3 - Y:1, Y1: 3, Ylist: [], Xdist: 2
Queens = [1, 2, 3] ;
noattack_3 - Y:3, Y1: 2, Ylist: [], Xdist: 1
noattack_3 - Y:1, Y1: 3, Ylist: [2], Xdist: 1
noattack_3 - Y:1, Y1: 2, Ylist: [], Xdist: 2
Queens = [1, 3, 2] ;
noattack_3 - Y:1, Y1: 3, Ylist: [], Xdist: 1
noattack_3 - Y:2, Y1: 1, Ylist: [3], Xdist: 1
noattack_3 - Y:2, Y1: 3, Ylist: [], Xdist: 2
Queens = [2, 1, 3] ;
noattack_3 - Y:3, Y1: 1, Ylist: [], Xdist: 1
noattack_3 - Y:2, Y1: 3, Ylist: [1], Xdist: 1
noattack_3 - Y:2, Y1: 1, Ylist: [], Xdist: 2
Queens = [2, 3, 1] ;
noattack_3 - Y:1, Y1: 2, Ylist: [], Xdist: 1
noattack_3 - Y:3, Y1: 1, Ylist: [2], Xdist: 1
noattack_3 - Y:3, Y1: 2, Ylist: [], Xdist: 2
Queens = [3, 1, 2] ;
noattack_3 - Y:2, Y1: 1, Ylist: [], Xdist: 1
noattack_3 - Y:3, Y1: 2, Ylist: [1], Xdist: 1
noattack_3 - Y:3, Y1: 1, Ylist: [], Xdist: 2
Queens = [3, 2, 1] ;
false.
请注意,除去约束后,它并没有生成有效的解决方案,而是显示了谓词执行值的生成,这正是我想要的。