I am trying to convert a simple Python program to Prolog.
I have reached the move()
function, and I'm stuck trying to do a basic list operation.
Here's move()
in 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
Here's my attempt at the Prolog version (plus additional context):
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].
I have narrowed down my problem to creating NewCellList
and my usage of length()
.
All I want to do is create a new list that is a copy of CellList
with a few elements at indices F
, O
, and T
set to different values.
Current output:
?- 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)
Desired Output:
?- 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)
Basically, this problem boils down to performing the following in Prolog:
c=list(d)
c[f]=0
c[o]=0
c[t]=1
What am I doing wrong?
EDIT
Here's the answer (helper that uses nth0/4
) applied to 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].
EDIT 2
Here's a simplified version based on feedback:
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].
EDIT 3
Here's an even simpler version (PegsLeft > 2 is unnecessary):
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].
Thanks!!