Я все еще изучаю Пролог, так что прости меня, если я сделаю какую-то основную ошибку здесь. Я добавил аннотации, чтобы объяснить, что, по моему мнению, делает код, на случай, если я ошибаюсь. Простите, если я объясняю очевидное местами.
n_queens(NumQueens, Answer) :-
length(Answer, NumQueens), %Answer must be a list of length NumQueens
queens_are_safe(Answer). %All queens in Answer must be safe
queens_are_safe([]). %If there are no queens, nobody's in danger
queens_are_safe([Queen | Queens]) :-
queen_is_safe(Queen, Queens), %Is the queen safe from her peers?
queens_are_safe(Queens). %Recursively check the other queens
queen_is_safe(_, []).
queen_is_safe(NewQueen, [Queen | Queens]) :-
not(same_column(NewQueen, Queen)),
not(same_row(NewQueen, Queen)),
not(diagonal(NewQueen, Queen)),
queen_is_safe(NewQueen, Queens). %Recursively ensure NewQueen is safe from other queens
diagonal(X/Y, X1/Y1) :- Y1 - Y = X1 - X. %If the X and Y deltas are equal, arguments are diagonal
same_column(X/_, X/_). %If the X coordinates are the same, it's the same column.
same_row(_/Y, _/Y). %If the Y coordinates are the same, it's the same row.
Я ожидаю, что Prolog создаст список Queens, свяжет его с Answer и повторяет до тех пор, пока не найдет список значений, удовлетворяющих всем условиям. Например, если NumQueens равен 2, он будет тестировать [0/0, 0/0], затем [1/0, 0/0] и т. Д.
Однако я подозреваю, что я здесь не прав. Здесь не работает стек трассировки:
Exit: (12) samecolumn(_15108/_15110, _15108/_15116) ? creep
Fail: (11) not(user:samecolumn(_15048, _15054)) ? creep
Очевидно, проблема в том, что он использует _15108 в качестве значений X для same_column. Я ожидал бы, что он тогда попробует same_column, но с другими значениями для X. Но он не пробует снова, он терпит неудачу и возвращает false для запроса n_queens(8,Ans).
Почему это?