我是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.
有人看到这里有什么问题吗?
答案 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).