Я пытаюсь преобразовать простую программу Python в Пролог.
Я достиг функции move()
и застрял, пытаясь выполнить базовую операцию со списком.
Вот move()
в Python:
def move(kd,fot) :
k,d=kd
f,o,t=fot
if d[f]==1 and d[o]==1 and d[t]==0 :
c=list(d)
c[f]=0 # moved away
c[o]=0 # remove jumped over
c[t]=1 # landing here after jump
return (k-1,c)
else :
return None
Вот моя попытка версии Пролога (плюс дополнительный контекст):
use_module(library(lists)).
moves(0,1,3).
moves(0,2,5).
moves(1,3,6).
moves(1,4,8).
moves(2,4,7).
moves(2,5,9).
moves(3,6,10).
moves(3,7,12).
moves(4,7,11).
moves(4,8,13).
moves(5,8,12).
moves(5,9,14).
moves(3,4,5).
moves(6,7,8).
moves(7,8,9).
moves(10,11,12).
moves(11,12,13).
moves(12,13,14).
step(Step, Reversed) :-
moves(F, O, T),
Step = [F, O, T],
Reversed = [T, O, F].
init(I, Board) :-
length(L0, 14),
maplist(=(1), L0),
nth0(I, Cells, 0, L0),
Board = [14, Cells].
move(Board, Move, BoardAfterMove) :-
[PegsLeft | [CellList]] = Board,
(step(Move, _); step(_, Move)),
PegsLeft > 2,
[F, O, T] = Move,
nth0(F, CellList, 1),
nth0(O, CellList, 1),
nth0(T, CellList, 0),
NewPegsLeft is PegsLeft-1,
nth0(F, NewCellList, 0),
nth0(O, NewCellList, 0),
nth0(T, NewCellList, 1),
nth0(I, CellList, V), % Questionable
I \= F, I \= O, I \= T, % Questionable
nth0(I, NewCellList, V), % Questionable
length(CellList, Length) = length(NewCellList, Length), % Questionable
BoardAfterMove = [NewPegsLeft, NewCellList].
Я сузил свою задачу до создания NewCellList
и моего использования length()
.
Все, что я хочу сделать, это создать новый список, который является копией CellList
с несколькими элементами с индексами F
, O
и T
, для которых установлены разные значения.
Токовый выход:
?- move([14,[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]], Move, Board).
Move = [3, 1, 0],
Board = [13, [1, 0, 1, 0|_G7261]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, 1|_G7267]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, 1|_G7270]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, 1|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
Move = [3, 1, 0],
Board = [13, [1, 0, _G7257, 0, _G7266, _G7269, _G7272|...]] ;
% (results for next move, [5, 2, 0] omitted)
Требуемый выход:
?- move([14,[0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]], Move, Board).
Move = [3, 1, 0],
Board = [13, [1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] ;
% (results for next move, [5, 2, 0] omitted)
По сути, эта проблема сводится к выполнению в Прологе следующего:
c=list(d)
c[f]=0
c[o]=0
c[t]=1
Что я делаю не так?
EDIT
Вот ответ (помощник, который использует nth0/4
), примененный к move()
:
setat(P,LO,V,LN):-nth0(P,LO,_,T),nth0(P,LN,V,T).
move(Board, Move, BoardAfterMove):-
[PegsLeft | [CellList]] = Board,
(step(Move, _) ; step(_, Move)),
PegsLeft > 2,
[F, O, T] = Move,
nth0(F, CellList, 1),
nth0(O, CellList, 1),
nth0(T, CellList, 0),
NewPegsLeft is PegsLeft-1,
setat(F, CellList, 0, NewCellList0),
setat(O, NewCellList0, 0, NewCellList1),
setat(T, NewCellList1, 1, NewCellListFinal),
BoardAfterMove = [NewPegsLeft, NewCellListFinal].
РЕДАКТИРОВАТЬ 2
Вот упрощенная версия, основанная на отзывах:
setat(Index, List, Val, OldVal, Result):-
nth0(Index, List, OldVal, BeforeSet),
nth0(Index, Result, Val, BeforeSet).
move(Board, Move, BoardAfterMove):-
[PegsLeft | [CellList]] = Board,
(step(Move, _) ; step(_, Move)),
PegsLeft > 2,
[F, O, T] = Move,
NewPegsLeft is PegsLeft-1,
setat(F, CellList, 0, 1, NewCellList0),
setat(O, NewCellList0, 0, 1, NewCellList1),
setat(T, NewCellList1, 1, 0, NewCellListFinal),
BoardAfterMove = [NewPegsLeft, NewCellListFinal].
РЕДАКТИРОВАТЬ 3
Вот еще более простая версия (PegsLeft> 2 не требуется):
move(Board, Move, BoardAfterMove):-
[PegsLeft | [CellList]] = Board,
(step(Move, _); step(_, Move)),
[F, O, T] = Move, NewPegsLeft is PegsLeft-1,
set_at(F, CellList, 0, 1, NewCellList0),
set_at(O, NewCellList0, 0, 1, NewCellList1),
set_at(T, NewCellList1, 1, 0, NewCellListFinal),
BoardAfterMove = [NewPegsLeft, NewCellListFinal].
Спасибо !!