Prolog列表元素编辑

时间:2014-12-08 17:32:09

标签: 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大于列表中的元素数时,如何避免错误?

3 个答案:

答案 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).

Demo.

  

我想从列表中删除零

您需要为此添加另一个子句:

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

Demo.

答案 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]