List Prolog列表元素编辑

List Prolog列表元素编辑,list,recursion,prolog,predicate,subtraction,List,Recursion,Prolog,Predicate,Subtraction,我需要写一个谓词,它将取一个数字列表和一个数字X,然后从这个列表的X元素开始,从第一个元素减去1。 这可能看起来很容易,但我对这种语言还不熟悉,不能正确地书写 以下是我现在得到的: sub([H|T], X):-NEWH is H-1, NEWX is X-1, sub(T, NEWX). 但我怎样才能结束这一诅咒呢?像这样 sub([H|T], 0). 当X大于列表中的元素数时,如何避免错误?您需要做四件事: 为结果添加一个参数-您的规则生成一个新列表,需要在其中添加一个额外的参数。 当X

我需要写一个谓词,它将取一个数字列表和一个数字X,然后从这个列表的X元素开始,从第一个元素减去1。 这可能看起来很容易,但我对这种语言还不熟悉,不能正确地书写

以下是我现在得到的:

sub([H|T], X):-NEWH is H-1, NEWX is X-1, sub(T, NEWX).
但我怎样才能结束这一诅咒呢?像这样

sub([H|T], 0).

当X大于列表中的元素数时,如何避免错误?

您需要做四件事:

为结果添加一个参数-您的规则生成一个新列表,需要在其中添加一个额外的参数。 当X为零时,添加一个基本情况-你的sub[H | T],0。可以进一步简化为子类0。为了确保接受负X,甚至可以将其设为sub_ux,X:-X=<0。 为列表为空时添加另一个基本情况-这将允许您处理X太大的情况:sub[],\ux。 确保当X为零时递归子句不适用-您所需要做的就是在递归子句中添加一个检查X>0。 下面是结果规则的外观:

sub(L,X,L) :- X =< 0.
sub([], _,[]).
sub([H|T], X, [NEWH|NEWT]) :- X > 0, NEWH is H-1, NEWX is X-1, sub(T, NEWX, NEWT).
我想从列表中删除零

您需要为此添加另一个条款:

sub(L,X,L) :- X =< 0.
sub([], _,[]).
sub([H|T], X, [NEWH|NEWT]) :- X > 0, NEWH is H-1, NEWH > 0, NEWX is X-1, sub(T, NEWX, NEWT).
sub([H|T], X, NEWT) :- X > 0, NEWH is H-1, NEWH =< 0, NEWX is X-1, sub(T, NEWX, NEWT).

Prolog是声明性的。这意味着一旦创建了一个对象,就不能对其进行修改。这对于大多数Prolog系统来说并不是严格正确的,但在许多情况下,执行这种黑客操作是不明智的

因此,您需要的是一个谓词,它将第一个列表作为输入,并生成一个新列表。对于您的示例,例如:

sub([],_,[]). %base case: you reached the end of the list, return an empty list as well
sub(L,0,L).   %base case: you reached zero, no more editing, return the list.
sub([H|T],X,[NewH|newT]) :- %recursive case, subtract one from the head and from X and perform recursion.
    NewH is H-1,
    NewX is X-1,
    sub(T,NewX,newT).
注:有两种基本情况:

sub[],,[]:您到达列表的末尾,可能X还没有达到零。然后返回一个空列表。 subL,0,L:X达到零,然后停止编辑并返回未触及的列表L。
1您的代码没有任何作用,因为您的NEWH不会在任何地方返回。 2您的代码应该返回完整的列表和修改的元素,因此您的递归应该通过以下方式之一停止: a将X与零进行比较并追加列表的其余部分 或 b重复出现,直到列表结束,并每次将X与0进行比较

第一种方法很简单:

sub(L, 0, L).
sub([H|T], X, [H1 | Res]) :- 
    H1 is H-1,
    X1 is X-1,
    sub(T, X1, Res).
然后打电话:

>>> sub([1,2,3,4,5,6,7], 4, L).
L = [0, 1, 2, 3, 5, 6, 7]

非常感谢你!还有一个问题-如果减去1后的元素等于0,那么我想从列表中删除它。我应该在何处添加此代码?@veronicaxo如果要从列表中删除零,请添加一个类似于递归子句的单独子句。请查看编辑。谢谢,但它不应该返回[5,6,8,9]而不是[5,6,7,8,9]]吗@Veronicaxo你是对的,我应该去掉NEWT周围的方括号。顺便说一句:在你的表意文字链接中,你写道:-目标要执行。其内容应为:-要执行的初始化目标。