删除列表中的子列表,给定数字N,表示连续元素PROLOG

时间:2014-01-02 18:51:44

标签: list prolog sublist

我正在尝试解决Prolog练习。它表示如果F是从I中删除元素数量的结果,如N表示从位置P开始,它会起作用。 我也有一些基本情况需要解决:

  • 如果起始位置(P)大于初始列表(I)长度,那么我们得到I。
  • 如果要删除的元素数量(N)大于列表中元素的数量 从给定的位置(P),它将删除所有元素直到结束,给出作为
    结果是一个空列表。
  • 如果要移除的元素数量(N)为零,则结果为I.

这里有一些例子:

?- remove_at([],7,3,F).% working
F = []
?- remove_at([k1,k2], 5, 3,F).%working
F=[k1,k2]
?- remove_at([k1,k2], 2, 5,F).%need help
F=[k1]
?- remove_at([k1,k2,k3,k4,k5], 1, 2,F).%need help
F=[k3,k4,k5]

我所拥有的代码,它根本不起作用,只是在我指出的2个案例中需要帮助:

remove_at([],_,N,[]):-!.                  % for the base case
remove_at( Xs , _ , 0 , Xs ).             % both counts are done to zero: we're done.
remove_at( [X|Xs] , P , N , [X|Ys] ) :-   % otherwise...
P > 0 ,                                   % - when P > 0
P1 is P-1 ,                               % - decrement P
remove_at(Xs,P1,N,Ys).                    % - recurse down , adding the head of the     source list to the result list                                     
remove_at( [X|Xs] , 0 , N , Ys ) :-       % otherwise...
N > 0 ,                                   % - when N is > 0
N1 is N-1 ,                               % - decrement N
remove_at( Xs , 0 , N1 , Ys ).            % recurse down, discarding the head of the source list.

2 个答案:

答案 0 :(得分:3)

尼古拉斯有正确的想法。这是一个更正版本:

% Removing items from empty list is empty list
remove_at([], _, _, []).

% Remove 0 items gives the same list back
remove_at(L, _, 0, L).

% To remove items starting at location P, allow the head of the input
% to be in the output, and remove items starting at location P-1 in the tail.
remove_at([X|T], P, N, [X|R]) :-
    P > 1,
    P1 is P-1,
    remove_at(T, P1, N, R).

% Primary case: remove items starting at current position 1
% Remove the head, then remove N-1 items from the tail.
remove_at([_|T], 1, N, R) :-
    N > 0,
    N1 is N-1,
    remove_at(T, 1, N1, R).

答案 1 :(得分:1)

我不确定这是否涵盖了所有基本情况,但你可以这样做:

remove_at( Xs , 0 , 0 , Xs ) .            % both counts are done to zero: we're done.
remove_at( [X|Xs] , P , N , [X|Ys] ) :-   % otherwise...
  P > 0 ,                                 % - when P > 0
  P1 is P-1 ,                             % - decrement P
  remove_at(Xs,P1,N,Ys)                   % - recurse down , adding the head of the source list to the result list
  .                                       %
remove_at( [X|Xs] , 0 , N , Ys ) :-       % otherwise...
  N > 0 ,                                 % - when N is > 0
  N1 is N-1 ,                             % - decrement N
  remove_at( Xs , 0 , N1 , Ys )           % recurse down, discarding the head of the source list.
  .

或者您可以将其分解为更小的问题,列出以下内容。我们创建一个帮助器谓词(partition/4),它将列表拆分为最多指定长度和后缀的前缀,后缀由剩余的任何内容组成。

其余的很简单:我们调用partition/4前缀来获取我们想要保留的前缀及其余部分,然后我们将余数分为前缀,我们要丢弃的元素及其后缀,尾部我们想要保留的元素,然后追加我们想要保留的前缀,并保留结果列表。

remove_at( Xs , P , N , Ys ) :-
  partition(Xs,P,Pfx,Ts) ,       % split the source list into a prefix (Pfx) of [at most] length P and a suffix (Ts), consisting of the remainder.
  partition(Ts,N,_,Sfx) ,        % partition that suffix into a prefix (_) of [at most] length N (the elements to discard) and a suffix (Sfx) consisting of the remainder.
  append( Pfx, Sfx , Ys )        % append Pfx and Sfx to create the result list (Ys).
  .                              % Easy!

partition( Xs , 0 , [] , Xs ) .         % success if the count is down to zero: finalize the prefix.
partition( [X|Xs] , N , [X|T] , R ) :-  % otherwise...
  N > 0 ,                               % - when N > 0
  N1 is N-1 ,                           % - decrement N
  partition( Xs , N1 , T , R )         % - recurse down, prepending the head of the source list to the prefix.
  .

他们说,有多种方法可以做到。