Prolog代码删除列表的第n个元素

时间:2014-05-07 21:08:22

标签: prolog

我为我的作业编写了Prolog代码,以删除给定列表的第n个元素。

我创建了一个名为remove/3的谓词,它从列表中删除了一个元素,另一个名为drop2/4的谓词仅通过可被整除的数字调用remove/3谓词ñ

但是有一个小的逻辑错误,因为它只从列表中删除了1个元素,它是可被N整除的最后一个元素。我想这是因为当我用列表L调用remove/3谓词时X它将所有元素添加到X然后删除元素编号N,但是,L保持不变,所以当我再次用另一个N调用remove/3时,它不会继续上一次编辑,所以之前的编辑已删除的元素已恢复,因此只删除了最后一个元素。

查询示例:

drop([a,b,c,d,e,f,g,h,i,k], 3, X). 

结果应为:X = [a,b,d,e,g,h,k]

drop(L, N, X):-
    drop2(L, N, X, N).

drop2(_, _, _, 1).

drop2(L, N, X, C):-
    N mod C =:= 0,
    remove(L, N, X),
    Z is C-1,
    drop2(L, N, X, Z).

drop2(L, N, X, C):-
    Z is C-1,
    drop2(L, N, X, Z).

remove([_|T], 1, T).
remove([H|T1], N, [H|T2]):-
    N > 1,
    Z is N - 1,
    remove(T1, Z, T2).

2 个答案:

答案 0 :(得分:2)

这对我来说似乎很复杂。你可以说

drop(Xs,N,Rs) :-
  integer(N) ,
  N > 0 ,
  drop(Xs,1,N,Rs)
  .

你的助手谓词drop/4

drop( []     , _ , _ , [] ) .
drop( [X|Xs] , P , N , Rs ) :-
  ( 0 =:= P mod N -> R1 = Rs ; [X|R1] = Rs ) ,
  P1 is P+1 ,
  drop(Xs,P1,N,R1)
  .

或等效的

drop( []     , _ , _ , [] ) .
drop( [X|Xs] , P , N , [X|Rs] ) :- 0 =\= P mod N , P1 is P+1 , drop(Xs,P1,N,Rs) .
drop( [_|Xs] , P , N ,    Rs  ) :- 0 =:= P mod N , P1 is P+1 , drop(Xs,P1,N,Rs) .

甚至

drop( []     , _ , _ , []     ) .
drop( [_|Xs] , P , P ,    Rs  ) :-         P1 is   1 , drop(Xs,P1,N,Rs) .
drop( [X|Xs] , P , N , [X|Rs] ) :- P < N , P1 is P+1 , drop(Xs,P1,N,Rs) .

答案 1 :(得分:2)

无需编写递归代码......只需使用append/3length/2same_length/2

list_nth1_dropped(As,N1,Bs) :-
   same_length(As,[_|Bs]),
   append(Prefix,[_|Suffix],As),
   length([_|Prefix],N1),
   append(Prefix,Suffix,Bs).

以下是OP给出的查询:

?- Xs = [a,b,c,d,e,f,g,h,i,k],
   list_nth1_dropped(Xs,3,Ys).
  Xs = [a,b,c,d,e,f,g,h,i,k],
  Ys = [a,b,  d,e,f,g,h,i,k]
; false.

更一般的查询怎么样?

?- list_nth1_dropped([a,b,c,d,e,f],N,Xs).
  N = 1, Xs = [  b,c,d,e,f]
; N = 2, Xs = [a,  c,d,e,f]
; N = 3, Xs = [a,b,  d,e,f]
; N = 4, Xs = [a,b,c,  e,f]
; N = 5, Xs = [a,b,c,d,  f]
; N = 6, Xs = [a,b,c,d,e  ]
; false.