Prolog总结了列表的第一个索引

时间:2017-02-03 00:04:09

标签: list recursion prolog

我是Prolog的新手,试图只总结每个列表的第一个元素。

takeFirst([[1,2,3],[4,5,6],[7,8,9]],R).   --> R=1+4+7=12

它一直输出错误,我不明白我在这里缺少什么。

takeFirst([HF|_],[],HF):-!. 
takeFirst([H|L1],R):- H=[_|_], L1=[_|_],!,takeFirst(H,L1,NN), R is NN.
takeFirst([HF|_],[K|L2],HF):- takeFirst(K,L2,NN), HF is HF+NN. 

有人看到这里有什么问题吗?

1 个答案:

答案 0 :(得分:1)

你的代码相当混乱:你首先定义一个takeFirst/3(可能应该是基本情况?)。接下来,您定义了两个递归情况,但是您以某种方式在递归调用中传递 head 列表等。

实际上问题很容易解决。您最好使用累加器takeFirst/2重定向到takeFirst / 3`:

takeFirst(L,R) :-
    takeFirst(L,0,R).

接下来我们考虑一个基本情况:我们到达了列表的末尾:

takeFirst([],R,R).

在这种情况下,我们到达了结尾,因此累加器的值,即我们传递的变量,它跟踪到目前为止的总和,作为结果返回。

在递归的情况下,我们会得到一个列表[H|T],我们感兴趣的是头部 HH所以[[HH|_]|T]。在这种情况下,我们将HH添加到累加器并使用T进行递归调用:

takeFirst([[HH|_]|T],Ra,R) :-
    Rb is Ra+HH,
    takeFirst(T,Rb,R).

所以把它放在一起我们得到:

takeFirst(L,R) :-
    takeFirst(L,0,R).

takeFirst([],R,R).
takeFirst([[HH|_]|T],Ra,R) :-
    Rb is Ra+HH,
    takeFirst(T,Rb,R).

在您的问题中不太清楚的是,如果列表中有空列表,例如[[1,2,3],[],[7,8,9]],应该怎么做。上面的谓词将失败:它期望所有列表至少有一个元素。如果您只是想忽略这些列表,可以将代码更改为:

takeFirst2(L,R) :-
    takeFirst2(L,0,R).

takeFirst2([],R,R).
takeFirst2([[]|T],Ra,R) :-
    takeFirst2(T,Ra,R).
takeFirst2([[HH|_]|T],Ra,R) :-
    Rb is Ra+HH,
    takeFirst2(T,Rb,R).

因此我们添加一个案例,其中列表遵循模式[[]|T],在这种情况下,我们只使用尾T执行递归调用。

根据上面给出的谓词,构建一个头列表并不难:

heads([],[])
heads([[HH|_]|TA],[HH|TB]) :-
    heads(TA,TB).