如何从序言中的列表中修剪前 N 个元素

Sam*_*nga -2 concat list trim prolog

如何编写 prolog 程序以使用 conc 操作从 prolog 中的 List 中修剪前 N 个元素。

trim(L1,N,L2) which is true if L2 contains the first N elements of L1 
Run Code Online (Sandbox Code Playgroud)

有人能帮帮我吗。

这是我的答案,正确吗?

trim(L1, N, L2):- conc(L2,T,L1), length(L2,N),length(L1,N2), N2>= N
Run Code Online (Sandbox Code Playgroud)

Nic*_*rey 5

简单的解决方案使用length/2append/3,沿着这些路线:

trim(L,N,S) :-    % to trim N elements from a list
  length(P,N) ,   % - generate an unbound prefix list of the desired length
  append(P,S,L) . % - and use append/3 to get the desired suffix.
Run Code Online (Sandbox Code Playgroud)

请注意,顺序并不重要。这也将起作用:

trim(L,N,S) :-    % to trim N elements from a list
  append(P,S,L) , % - split L into a prefix and suffix
  length(P,N) .   % - succeed if the prefix is of the desired length
Run Code Online (Sandbox Code Playgroud)

我想你的导师希望你找出一个/递归解决方案。人们可能会注意到,从列表左端修剪项目的算法非常简单:

  • 遍历列表直到您访问过N元素。
  • 一旦你这样做了,剩下的就是想要的结果。

这导致了一个简单的解决方案:

trim( L     , 0 , L ) .  % Trimming zero elements from a list yields the original, unchanged list
trim( [H|T] , N , R ) :- % Otherwise,
  N > 0 ,                % - assuming N is greater than zero
  N1 is N-1 ,            % - we decrement N
  trim( T , N1 , R )     % - and recurse down, discarding the head of the list.
  .                      % That's about all there is too it.
Run Code Online (Sandbox Code Playgroud)

如果你想学究,可以强制执行一个约束,即列表实际上应该是一个列表(或至少是类似列表),例如:

trim( []    , 0 , []    ) .  % Trimming zero elements from the empty list yields the empty list
trim( [H|T] , 0 , [H|T] ) .  % Trimming zero elements from a non-empty list yields the same list  
trim( [H|T] , N , R     ) :- % Otherwise,
  N > 0 ,                    % - given that N is greater than zero
  N1 is N-1 ,                % - we decrement N
  trim( T , N1 , R )         % - and recurse down, discarding the head of the list.
  .                          % That's about all there is to it.
Run Code Online (Sandbox Code Playgroud)

请注意,类似

trim( [a,b,c] , 5 , R ) .
Run Code Online (Sandbox Code Playgroud)

将失败:看看你是否能弄清楚如何使上面的事情成功,使用R = []. 提示:这并不难。

编辑为注意:如果您确实想要获取列表的第 1 个 N 元素,那并不困难:

prefix_of(L,N,P) :-
  append(P,_,L) ,
  length(P,N)
  .
Run Code Online (Sandbox Code Playgroud)

或者,滚动您自己的,您可以执行以下操作:

prefix_of( _      , 0 , []     ) .  % once we've counted down to zero, close the result list and succeed.
prefix_of( [X|Xs] , N , [X|Ys] ) :- % otherwise,
  N > 1 ,                           % - given that N is greater than zero,
  N1 is N-1 ,                       % - decrement N
  prefix_of( Xs , N1 , Ys )         % - and recurse down, with X prepended to the resullt list.
  .                                 % Again, that's about all there is to it.
Run Code Online (Sandbox Code Playgroud)

  • *请注意,顺序并不重要*它很重要。两个版本都具有不同的终止行为。 (2认同)