2

sublist(L1,L2,I,J)

我有一个列表,L1正在传入,以及 2 个索引Iand J,我想成为包含andL2之间元素的包容性子列表。 如果超出范围,我希望它从列表的末尾开始。同样,如果小于 0,我想让它从列表的开头到. >返回空列表。 IJ
JIIJIJ

到目前为止我所拥有的:

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).
4

2 回答 2

4

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

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

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

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

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

  • J超出列表末尾
  • I在列表开头之前

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

好的,让我们尝试实现它,我将使用一个累加器并将调用包装在它周围。

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

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

让我们处理基本情况。

空列表作为输入,只需将累加器与我们的输出列表统一即可。在这一点上,我们不关心指数。事实证明,这也满足了J超出列表末尾的边缘情况。因为那时我们将把所有的输入列表累加到累加器中,并且还剩下一个 J 值。

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

I > 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].
于 2013-05-08T03:22:15.700 回答
0

我认为您在第二个子句中有一些错字。试试这个(未经测试的)更正,需要满足您的要求

如果 J 超出范围,我希望它从 I 到列表的末尾。

sublist(Xs,Ys,I,J):-
    length(Xs,Length),
    J > Length,
    sublist(Xs,Ys,I,Length).
于 2013-05-08T05:13:37.703 回答