复制列表并在Prolog中按索引更改一些元素

时间:2018-11-08 01:43:33

标签: list prolog

我正在尝试将简单的Python program转换为Prolog。

我已经达到了move()函数,并且在尝试执行基本列表操作时遇到了困难。

在Python中为move()

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

这是我尝试的Prolog版本(以及其他上下文):

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的副本,其中索引FOT上的一些元素设置为不同值。

当前输出:

?- 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)

基本上,此问题归结为在Prolog中执行以下操作:

c=list(d)
c[f]=0
c[o]=0
c[t]=1

我在做什么错了?

编辑

以下是应用于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].

谢谢!

1 个答案:

答案 0 :(得分:2)

例如nth0 / 4:

?- [user].
|: setat(P,LO,V,LN) :- nth0(P,LO,_,T),nth0(P,LN,V,T).
% user://1 compiled 0.11 sec, 1 clauses
true.

?- setat(2,[a,b,c,d],0,R).
R = [a, b, 0, d].