Код в первой части вопроса объясняется здесь. Код размещен здесь, чтобы читатель не ошибочно посмотрел на неправильный код.
queens(N,Qs) :-
length(Qs,N),
place_queens(N,Qs,_,_).
place_queens(0,_Qs,_Ups,_Downs).
place_queens(I,Qs,Ups,[_|Downs]) :-
I > 0, I1 is I-1,
place_queens(I1,Qs,[_|Ups] ,Downs),
place_queen(I,Qs,Ups,Downs).
place_queen(Q,[Q|_],[Q|_],[Q|_]).
place_queen(Q,[_|Qs],[_|Ups],[_|Downs] ):-
place_queen(Q,Qs,Ups,Downs).
Этот код, как и большинство решений Prolog для задачи N-Queens, генерируется и тестируется. Код генерирует возможное решение и проверяет его. Однако вместо того, чтобы генерировать все позиции для одного возможного ответа одновременно, позиции ферзя устанавливаются постепенно и меняются при частичном сбое до тех пор, пока не будет найдено полное решение.
В коде есть один письменный тест, который
place_queen(Q,[Q|_],[Q|_],[Q|_]).
Чтобы понять это, необходимо понять, в чем смысл аргументов, связанных с этим утверждением из здесь
Теперь представьте, что шахматная доска разделена на три слоя, один
это касается атак на столбцы и две для диагоналей, идущих вверх и вниз соответственно.
Первый аргумент представляет ферзь, идентифицируемый положительным целым числом и связанный.
Второй аргумент представляет столбец и всегда представляет собой список размера доски, где каждое зелье в списке представляет один из столбцов доски.
Код использует переменную Qs для, но для меня это имеет больше смысла как Rs, то есть строки. Так что если в позиции в списке есть какое-либо связанное значение, которое будет королевой, атакующей в этом столбце.
Третий и четвертый аргументы работают в принципе одинаково и заботятся о диагональной атаке королевы. Один для диагоналей идет вверх, а другой диагоналей идет вниз. Поскольку они снова являются диагоналями, они представлены в виде списка, но в зависимости от зелья ферзя на проверяемой доске размер диагонали вверх может отличаться от размера диагонали вниз.
Например, на изображении ниже белая королева представляет положение проверяемой королевы, а черные королевы, идущие по диагонали вверх, представляют восходящий диагональный список, а другая королева представляет нисходящий диагональный список.
Примечание: изображения, созданные с использованием Настройка шахматной диаграммы
Диагональ спуска вверх равна длине двух, а диагональ спада - длине единицы.
В тесте говорится, что если ферзь, заданный в первом аргументе, может быть объединен с аргументом атаки столбца, диагональной атакой вверх и диагональной атакой вниз, то он принимает королеву в этой позиции для частичного ответа или полного ответьте, если ферзь находится в последней позиции списка во втором аргументе.
Так что для теста
place_queen(Q,[Q|_],[Q|_],[Q|_]).
что совпадает с написанным для ясности и документации
place_queen(Q,Rs,Ups,Downs) :-
Rs = [R_1|_],
Ups = [U_1|_],
Downs = [D_1|_],
Q = R_1, Q = U_1, Q = D_1
тогда если
Q равно 1
R_1 не связан
U_1 не связан
D_1 не связан
Тестовое прошлое и 1 связаны с переменными R_1, U_1 и D_1.
и пример теста, который не прошел
Q - 3
R_1 составляет 1
U_1 не связан
D_1 не связан
Теперь для вызова, который не проходит как тест из-за отсутствия значения в списке.
Q равно 2
R_1 это []
U_1 не связан
D_1 не связан
Остальная часть кода просто генерирует кейсы для тестирования.
Второй аргумент можно увидеть генерирующим при запуске этого варианта кода.
queens(N) :-
length(Qs,N),
format("N: ~w, Qs: ~w~n",[N,Qs]).
?- queens(4).
N: 4, Qs: [_6476,_6482,_6488,_6494]
true.
Диагональные аргументы можно увидеть, генерируя этот вариант кода.
queens(N) :-
length(Qs,N),
place_queens(N,Qs,_,_).
place_queens(0,_Qs,_Ups,_Downs).
place_queens(I,Qs,Ups,[_|Downs]) :-
I > 0,
I1 is I-1,
place_queens(I1,Qs,[_|Ups] ,Downs),
format('I1: ~w, Qs: ~w, Ups: ~w, Downs: ~w~n',[I1,Qs,Ups,Downs]).
?- queens(4).
I1: 0, Qs: [_6474,_6480,_6486,_6492], Ups: [_6528,_6516,_6504|_6506], Downs: _6536
I1: 1, Qs: [_6474,_6480,_6486,_6492], Ups: [_6516,_6504|_6506], Downs: [_6534|_6536]
I1: 2, Qs: [_6474,_6480,_6486,_6492], Ups: [_6504|_6506], Downs: [_6522,_6534|_6536]
I1: 3, Qs: [_6474,_6480,_6486,_6492], Ups: _6506, Downs: [_6510,_6522,_6534|_6536]
true ;
false.
эта маленькая часть
place_queen(Q,[_|Rs],[_|Ups],[_|Downs] ):-
place_queen(Q,Rs,Ups,Downs).
просто говорит, что если позиция для следующей королевы не работает для строки в столбце, выберите другую строку. Обратите внимание, что в приведенном выше примере имя переменной второго аргумента изменяется с Qs
на Rs
, чтобы сказать, что это строка, которая изменяется.
Чтобы было проще увидеть генерацию и тестирование в действии, измените код как таковой
queens(N,Qs) :-
length(Qs,N),
place_queens(N,Qs,_,_).
place_queens(0,_Qs,_Ups,_Downs).
place_queens(I,Qs,Ups,[_|Downs]) :-
I > 0,
I1 is I-1,
place_queens(I1,Qs,[_|Ups] ,Downs),
format('Generate 1 - I: ~w, Qs: ~w, Ups: ~w, Downs: ~w~n',[I,Qs,Ups,Downs]),
place_queen(I,Qs,Ups,Downs),
format('Result -> I: ~w, Qs: ~w, Ups: ~w, Downs: ~w~n',[I,Qs,Ups,Downs]).
place_queen(Q,Rs,Ups,Downs) :-
Rs = [R_1|_],
Ups = [U_1|_],
Downs = [D_1|_],
format('Test - Q : ~w, R_1: ~w, U_1: ~w, D_1: ~w~n',[Q,R_1,U_1,D_1]),
(
Rs = [Q|_],
Ups = [Q|_],
Downs = [Q|_]
->
format('Test success~n')
;
format('Test failure~n'),
fail
).
place_queen(Q,[_|Qs],[_|Ups],[_|Downs] ):-
format('Generate 2 - Q: ~w, Qs: ~w, Ups: ~w, Downs: ~w~n',[Q,Qs,Ups,Downs]),
place_queen(Q,Qs,Ups,Downs).
Пример запуска до первого решения.
?- queens(4,Qs).
Generate 1 - I: 1, Qs: [_6488,_6494,_6500,_6506], Ups: [_6542,_6530,_6518|_6520], Downs: _6550
Test - Q : 1, Q_1: _6488, U_1: _6542, D_1: _6596
Test success
Result -> I: 1, Qs: [1,_6494,_6500,_6506], Ups: [1,_6530,_6518|_6520], Downs: [1|_6598]
Generate 1 - I: 2, Qs: [1,_6494,_6500,_6506], Ups: [_6530,_6518|_6520], Downs: [_6548,1|_6598]
Test - Q : 2, Q_1: 1, U_1: _6530, D_1: _6548
Test failure
Generate 2 - Q: 2, Qs: [_6494,_6500,_6506], Ups: [_6518|_6520], Downs: [1|_6598]
Test - Q : 2, Q_1: _6494, U_1: _6518, D_1: 1
Test failure
Generate 2 - Q: 2, Qs: [_6500,_6506], Ups: _6520, Downs: _6598
Test - Q : 2, Q_1: _6500, U_1: _6746, D_1: _6752
Test success
Result -> I: 2, Qs: [1,_6494,2,_6506], Ups: [_6530,_6518,2|_6748], Downs: [_6548,1,2|_6754]
Generate 1 - I: 3, Qs: [1,_6494,2,_6506], Ups: [_6518,2|_6748], Downs: [_6536,_6548,1,2|_6754]
Test - Q : 3, Q_1: 1, U_1: _6518, D_1: _6536
Test failure
Generate 2 - Q: 3, Qs: [_6494,2,_6506], Ups: [2|_6748], Downs: [_6548,1,2|_6754]
Test - Q : 3, Q_1: _6494, U_1: 2, D_1: _6548
Test failure
Generate 2 - Q: 3, Qs: [2,_6506], Ups: _6748, Downs: [1,2|_6754]
Test - Q : 3, Q_1: 2, U_1: _6902, D_1: 1
Test failure
Generate 2 - Q: 3, Qs: [_6506], Ups: _6898, Downs: [2|_6754]
Test - Q : 3, Q_1: _6506, U_1: _6932, D_1: 2
Test failure
Generate 2 - Q: 3, Qs: [], Ups: _6928, Downs: _6754
Generate 2 - Q: 2, Qs: [_6506], Ups: _6742, Downs: _6748
Test - Q : 2, Q_1: _6506, U_1: _6782, D_1: _6788
Test success
Result -> I: 2, Qs: [1,_6494,_6500,2], Ups: [_6530,_6518,_6740,2|_6784], Downs: [_6548,1,_6746,2|_6790]
Generate 1 - I: 3, Qs: [1,_6494,_6500,2], Ups: [_6518,_6740,2|_6784], Downs: [_6536,_6548,1,_6746,2|_6790]
Test - Q : 3, Q_1: 1, U_1: _6518, D_1: _6536
Test failure
Generate 2 - Q: 3, Qs: [_6494,_6500,2], Ups: [_6740,2|_6784], Downs: [_6548,1,_6746,2|_6790]
Test - Q : 3, Q_1: _6494, U_1: _6740, D_1: _6548
Test success
Result -> I: 3, Qs: [1,3,_6500,2], Ups: [_6518,3,2|_6784], Downs: [_6536,3,1,_6746,2|_6790]
Generate 1 - I: 4, Qs: [1,3,_6500,2], Ups: [3,2|_6784], Downs: [_6524,_6536,3,1,_6746,2|_6790]
Test - Q : 4, Q_1: 1, U_1: 3, D_1: _6524
Test failure
Generate 2 - Q: 4, Qs: [3,_6500,2], Ups: [2|_6784], Downs: [_6536,3,1,_6746,2|_6790]
Test - Q : 4, Q_1: 3, U_1: 2, D_1: _6536
Test failure
Generate 2 - Q: 4, Qs: [_6500,2], Ups: _6784, Downs: [3,1,_6746,2|_6790]
Test - Q : 4, Q_1: _6500, U_1: _7070, D_1: 3
Test failure
Generate 2 - Q: 4, Qs: [2], Ups: _7066, Downs: [1,_6746,2|_6790]
Test - Q : 4, Q_1: 2, U_1: _7100, D_1: 1
Test failure
Generate 2 - Q: 4, Qs: [], Ups: _7096, Downs: [_6746,2|_6790]
Generate 2 - Q: 3, Qs: [_6500,2], Ups: [2|_6784], Downs: [1,_6746,2|_6790]
Test - Q : 3, Q_1: _6500, U_1: 2, D_1: 1
Test failure
Generate 2 - Q: 3, Qs: [2], Ups: _6784, Downs: [_6746,2|_6790]
Test - Q : 3, Q_1: 2, U_1: _6962, D_1: _6746
Test failure
Generate 2 - Q: 3, Qs: [], Ups: _6958, Downs: [2|_6790]
Generate 2 - Q: 2, Qs: [], Ups: _6778, Downs: _6784
Generate 2 - Q: 1, Qs: [_6494,_6500,_6506], Ups: [_6530,_6518|_6520], Downs: _6586
Test - Q : 1, Q_1: _6494, U_1: _6530, D_1: _6626
Test success
Result -> I: 1, Qs: [_6488,1,_6500,_6506], Ups: [_6542,1,_6518|_6520], Downs: [_6584,1|_6628]
Generate 1 - I: 2, Qs: [_6488,1,_6500,_6506], Ups: [1,_6518|_6520], Downs: [_6548,_6584,1|_6628]
Test - Q : 2, Q_1: _6488, U_1: 1, D_1: _6548
Test failure
Generate 2 - Q: 2, Qs: [1,_6500,_6506], Ups: [_6518|_6520], Downs: [_6584,1|_6628]
Test - Q : 2, Q_1: 1, U_1: _6518, D_1: _6584
Test failure
Generate 2 - Q: 2, Qs: [_6500,_6506], Ups: _6520, Downs: [1|_6628]
Test - Q : 2, Q_1: _6500, U_1: _6776, D_1: 1
Test failure
Generate 2 - Q: 2, Qs: [_6506], Ups: _6772, Downs: _6628
Test - Q : 2, Q_1: _6506, U_1: _6806, D_1: _6812
Test success
Result -> I: 2, Qs: [_6488,1,_6500,2], Ups: [1,_6518,_6770,2|_6808], Downs: [_6548,_6584,1,2|_6814]
Generate 1 - I: 3, Qs: [_6488,1,_6500,2], Ups: [_6518,_6770,2|_6808], Downs: [_6536,_6548,_6584,1,2|_6814]
Test - Q : 3, Q_1: _6488, U_1: _6518, D_1: _6536
Test success
Result -> I: 3, Qs: [3,1,_6500,2], Ups: [3,_6770,2|_6808], Downs: [3,_6548,_6584,1,2|_6814]
Generate 1 - I: 4, Qs: [3,1,_6500,2], Ups: [_6770,2|_6808], Downs: [_6524,3,_6548,_6584,1,2|_6814]
Test - Q : 4, Q_1: 3, U_1: _6770, D_1: _6524
Test failure
Generate 2 - Q: 4, Qs: [1,_6500,2], Ups: [2|_6808], Downs: [3,_6548,_6584,1,2|_6814]
Test - Q : 4, Q_1: 1, U_1: 2, D_1: 3
Test failure
Generate 2 - Q: 4, Qs: [_6500,2], Ups: _6808, Downs: [_6548,_6584,1,2|_6814]
Test - Q : 4, Q_1: _6500, U_1: _7070, D_1: _6548
Test success
Result -> I: 4, Qs: [3,1,4,2], Ups: [_6770,2,4|_7072], Downs: [_6524,3,4,_6584,1,2|_6814]
Qs = [3, 1, 4, 2] .
Если вам трудно прочитать этот вывод здесь, потому что он широкий, а также трудно просмотреть в качестве вывода на верхний уровень (swipl.exe), тогда посмотрите, как использовать protocol / 1 для записать вывод в файл для просмотра и анализа.