在给定索引和许多元素的列表中创建子列表。序言

时间:2013-12-24 18:45:21

标签: list indexing prolog element sublist

我正在尝试解决一个简单的序言问题,但我无法解决它。从列表中需要创建一个给定索引I的子列表,然后从I给出下一个给定为N的元素。如果索引大于列表长度,我将得到子列表为空。如果N(元素的数量)大于列表中的其余元素,我将从I获得所有元素直到结束。

在这里,我得到了一部分作业,我可以从索引I得到下一个元素N.现在我询问作业中的其他部分:

1)当I(索引)长于列表长度时,我必须在子列表中获得一个空列表。

?- sublist([a,b,c,d],5,2,L)

L=[]

2)当N(下一个元素)大于我们休息的元素数量时,我需要从该位置获取所有元素直到结束。

?- sublist([a,b,c,d],4,4,L)

L=[d]      

我已经拥有的代码是下一个代码,这个代码正在运行:

sublist([X|_],1,1,[X]).
sublist([],_,_,[]).% I use this one for the case bases
sublist([X|Xs],1,K,[X|Ys]):-
       K>1, 
       K1 is K-1,
       sublist(Xs,1,K1,Ys).
sublist([_|Xs],I,K,Ys):-
       I > 1, 
       I1 is I-1,
       sublist(Xs,I1,K,Ys).

3 个答案:

答案 0 :(得分:2)

sublist([X|_], 1, 1, [X]).

这是一个很好的条款。它表示从[X|_]列表中选择的从1开始的长度为1的子列表为[X]

sublist([X|Xs], 1, K, [X|Ys]) :-
    K > 1, 
    K1 is K - 1,
    sublist(Xs, 1, K1, Ys).

这也是一个很好的条款。它表示从K开始的长度为[X|Xs]的子列表以X开头,并且尾部Ys是来自K-1的子列表从1开始的第一个列表(Xs)的尾部。

sublist([_|Xs], I, K, Ys) :-
    I > 1, 
    I1 is I - 1,
    K1 is K - 1,
    sublist(Xs, I1, K1, Ys).

此条款有问题。如果您有一个列表[_|Xs],并且想要从KI大于1)开始,请选择长度为I的子列表,则会获取长度为{{的子列表1}}从它的尾部开始,位置K-1。问题是:为什么子列表现在需要长度为I-1此子句的目的应该是将问题减少到您处理起始索引的情况K-1,然后让第二个条款处理其余部分。

然后在您对期望行为的定义中,您有:如果N(元素数量)大于列表中其余元素,我将从I获取所有元素直到结束。目前这个概念不属于任何条款。基本情况当前是您的第一个子句,特别需要长度为1来生成长度为1的列表。您需要另一个基本案例子句来处理第一个列表为空但1可能仍为任何值的情况:

K

只需填写sublist([], ?, _, ?). 符合逻辑的内容即可。 :)

答案 1 :(得分:2)

只是为了展示像nth1 / 3这样的不确定性内置组合如何帮助......

sublist(List, From, Count, SubList) :-
    findall(E, (nth1(I, List, E), I >= From, I < From + Count), SubList).

编辑一条说明,说这个“一个班轮”实际上比制作的子列表/ 4效率低得多。

实际上,

2 ?- N=1000000,length(L,N),time(sublist(L,N,1,V)).
% 3,000,014 inferences, 2.129 CPU in 2.134 seconds (100% CPU, 1409024 Lips)
N = 1000000,
L = [_G28, _G31, _G34, _G37, _G40, _G43, _G46, _G49, _G52|...],
V = [_G3000104].

3 ?- N=1000000,length(L,N),time(sublist(L,1,1,V)).
% 4,000,012 inferences, 2.549 CPU in 2.553 seconds (100% CPU, 1569076 Lips)
N = 1000000,
L = [_G28, _G31, _G34, _G37, _G40, _G43, _G46, _G49, _G52|...],
V = [_G3000104].

我将看看在findall'谓词中是否可以解决这个问题,但这不太可能。这个更好:

sublist(List, From, Count, SubList) :-
    To is From + Count - 1,
    findall(E, (between(From, To, I), nth1(I, List, E)), SubList).

18 ?- N=1000000,length(L,N),time(sublist(L,3,3,V)).
% 28 inferences, 0.000 CPU in 0.000 seconds (93% CPU, 201437 Lips)
N = 1000000,
L = [_G682, _G685, _G688, _G691, _G694, _G697, _G700, _G703, _G706|...],
V = [_G3000762, _G3000759, _G3000756].

答案 2 :(得分:0)

这是一个解决方案(虽然它可能不是你教授想要的):

sublist( Xs , Offset , Count , Ys ) :- %
  length(Prefix,Offset ) ,             % construct a list of variables of length 'offset'
  length(Ys,Count) ,                   % construct a list of variables of length 'count'
  append(Prefix,Suffix,Xs) ,           % strip the first first 'offset' items from the source list ,
  append(Ys,_,Suffix)                  % extract the first 'count' items from what's left.
  .                                    % easy!

这是一种方法,让Prolog的内置插件为您完成工作。

这是另一种不使用任何内置插件的方法。这个使用一个帮助器谓词,它只是简单地将列表拆分为指定长度的前缀,以及后缀,由剩余的任何内容组成。

sublist( Xs , Offset , Count , Ys ) :-
  split(Xs,Offset,_,X1) ,               % extract the first 'offset' items from the lsit and toss them
  split(X1,Count,Ys,_)                  % extract the first 'count' items from the remainder to get the result.
  .

split( []     , 0 , []     , []     ) .  % splitting a zero-length prefix from an empty list yields a zero-length prefix and a zero length suffix.
split( [X|Xs] , 0 , []     , [X|Xs] ) .  % splitting a zero-length prefix from a non-empty list yields a zero-length prefix and the non-empty list.
split( [X|Xs] , N , [X|Ps] , Qs     ) :- % Otherwise...
  N > 0 ,                                % - if the count is positive
  N1 is N-1 ,                            % - we decrement count
  split( Xs , N1 , Ps , Qs )             % - and recurse down, prepending the head of the source list to the prefix
  .                                      % Easy!