我正在尝试解决Prolog练习。它表示如果F是从I中删除元素数量的结果,如N表示从位置P开始,它会起作用。 我也有一些基本情况需要解决:
这里有一些例子:
?- 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.
答案 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.
.
他们说,有多种方法可以做到。