我需要编写一个谓词,它将获取一个数字列表和一个数字X,然后从该列表中的X个元素(从第一个开始)中减去1。 这似乎很容易,但我是这种语言的新手,我不能正确地写它。
以下是我现在所得到的:
sub([H|T], X):-NEWH is H-1, NEWX is X-1, sub(T, NEWX).
但是我怎么能结束这次递归呢?像这样?
sub([H|T], 0).
当X大于列表中的元素数时,如何避免错误?
答案 0 :(得分:0)
你需要做四件事:
X
为零时添加基本案例 - 您的sub([H|T], 0).
可以进一步简化为sub(_, 0).
为了确保您接受否定X
,您甚至可以制作它sub(_,X) :- X =< 0.
X
过大的情况:sub([], _).
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).
答案 1 :(得分:0)
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
尚未达到零。然后返回一个空列表。sub(L,0,L)
:X
达到零,然后您停止编辑并返回列表L
未显示。答案 2 :(得分:0)
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]