Prolog - 提取子列表

时间:2013-05-08 02:03:07

标签: list prolog

sublist(L1,L2,I,J)

我有一个列表,L1被传入,还有2个索引IJ,我希望L2成为包含两个元素之间元素的包含子列表IJ
如果J超出范围,我希望它从I转到列表的末尾。同样,如果I小于0,我想让它从列表的开头到JI> J返回空列表。

到目前为止我所拥有的:

sublist(_,[],I,J):-
    I > J.  
sublist(Xs,Ys,I,Length):-
    length(Xs,Length),
    N > L,
    sublist(Xs,Ys,I,J).  
sublist([X|_],[X],1,1).  
sublist([X|Xs],[X|Ys],1,J):-
    J > 1,
    J1 is J - 1,
    sublist(Xs,Ys,1,J1).  
sublist([_|Xs],Ys,I,J):-
    I > 1,
    I1 is I - 1,
    J1 is J - 1,
    sublist(Xs,Ys,I1,J1).

2 个答案:

答案 0 :(得分:4)

您可以通过重新思考策略来解决这个问题。

首先,您的基本情况是什么?

  • 您最终将空列表作为输入
  • 您有I > J

在这两种情况下,您都会将空列表附加到目前为止的任何内容,并将其称为好。

接下来,你关心的边缘情况是什么?

  • J超出了列表的末尾
  • I位于列表的开头
  • 之前

在第一种情况下,您只需遍历输入列表的末尾。在第二步中,您从输入列表的开头开始。

好的,让我们尝试实现它,我将使用累加器并围绕它进行调用。

sublist(L1, L2, I, J):-
    sublist(L1, Temp, I, J, []),
    !,
    reverse(Temp, L2).

我们将输入列表L1,一个变量统一为输出列表L2,以及索引IJ。我正在使用cut,因此我不必担心其他解决方案的回溯,并反转它,因为累积列表是反向构建的。

让我们研究基本案例。

清空列表作为输入,只需将累加器与输出列表统一起来。我们现在不关心指数。事实证明,这也满足了J超出列表末尾的边缘情况。从那时起,我们将所有输入列表累积到累加器中,并且仍然有剩余的J值。

sublist([], L2, _I, _J, L2).

我> J再次将累加器与输出列表统一起来。我们不再关心输入列表了。

sublist(_L1, L2, I, J, L2):-
    I > J.

现在是边缘案例。

列表末尾之外的

J已在上面解决。

I位于列表的开头之前,只需将该索引设置为0,然后继续。

sublist(L1, L2, I, J, L2):-
    I < 0,
    sublist(L1, L2, 0, J, L2).

现在我们只需要实现实际的逻辑。我们只想从正确的I开始积累。所以让我们递减I并丢弃输入列表的部分,直到我们到达我们想要的位置。为了使索引的结尾匹配,我们还需要递减J。这样我们在指数之间保持相同的距离。

sublist([_L|Ls], L2, I, J, Acc):-
    I > 0,
    sublist(Ls, L2, I-1, J-1, Acc).

我们终于想到了。所以,让我们开始使用输入列表中的片段构建列表。这一直持续到我们遇到一个基本情况为止。之后,累加器将返回到原始sublist子句。

sublist([L|Ls], L2, I, J, Acc):-
    sublist(Ls, L2, I, J-1, [L|Acc]).

总而言之,我们最终得到:

sublist(L1, L2, I, J):-
    sublist(L1, Temp, I, J, []),
    !,
    reverse(Temp, L2).
sublist([], L2, _I, _J, L2).
sublist(_L1, L2, I, J, L2):-
    I > J.
sublist(L1, L2, I, J, L2):-
    I < 0,
    sublist(L1, L2, 0, J, L2).
sublist([_L|Ls], L2, I, J, Acc):-
    I > 0,
    sublist(Ls, L2, I-1, J-1, Acc).
sublist([L|Ls], L2, I, J, Acc):-
    sublist(Ls, L2, I, J-1, [L|Acc]).

我们可以这样测试它:

?- sublist([1,2,3,4,5], S, 0,3).
S = [1, 2, 3, 4].

?- sublist([1,2,3,4,5], S, -1,30).
S = [1, 2, 3, 4, 5].

?- sublist([1,2,3,4,5], S, 3,1).
S = [].

?- sublist([1,2,3,4,5], S, 3,3).
S = [4].

?- sublist([1,2,3,4,5], S, 3,4).
S = [4, 5].

答案 1 :(得分:0)

我认为你在第二个条款中只有一些错字。尝试这种(未经测试的)校正,以满足您的要求

  

如果J超出界限,我希望它从我到列表的末尾。

sublist(Xs,Ys,I,J):-
    length(Xs,Length),
    J > Length,
    sublist(Xs,Ys,I,Length).