我很难弄清楚如何找到像这样的成对列表中的整数之和:
[[a, 1], [b, 2], [c, 3], [d, 4]]
我尝试过类似的操作,因为它让人想起常规的求和函数:
sum([], 0).
sum([[_,Head]|[_,Tail]], Sum) :-
sum([_,Tail], Sum2),
Sum is Head+Sum2.
正在通话:
sum([[a, 1], [b, 2], [c, 3], [d, 4]], Total),
write('Sum = '), write(Total).
但这不起作用。当它应该打印出总和时,它会打印出false,这是10。
答案 0 :(得分:1)
我认为将其分为两个任务可能会有所帮助:
这使解决两个问题变得更加容易,此外,您现在还有两个额外的谓词可用于其他目的。
我们可以通过以下方式获得子列表的第二项的列表:
item2list([], []).
item2list([[_, X|_]|T], [X|T2]) :-
item2list(T, T2).
或者我们可以使用https://www.instagram.com/p/Bwedsp-HEF3/和maplist/3
[swi-doc]:
item2list(L1, L2) :-
maplist(nth1(2), L1, L2).
或者我们可以用nth1/3
[swi-doc]和findall/3
[swi-doc]来写item2list
:
item2list(L1, L2) :-
findall(X, member([_,X|_], L1), L2).
尽管这里的谓词不是双向的。
例如:
?- item2list([[a, 1], [b, 2], [c, 3], [d, 4]], L).
L = [1, 2, 3, 4].
我将汇总列表作为练习。
答案 1 :(得分:1)
尝试定义谓词sum/2
时,您没有正确处理列表列表。试试:
sum(Lists, Sum) :-
sum(Lists, 0, Sum).
sum([], Sum, Sum).
sum([[_,N]| Lists], Sum0, Sum) :-
Sum1 is Sum0 + N,
sum(Lists, Sum1, Sum).
此版本使用累加器启用尾递归定义。通话示例:
| ?- sum([[a, 1], [b, 2], [c, 3], [d, 4]], Sum).
Sum = 10
yes
答案 2 :(得分:0)
每当您期望成功的目标失败时,将其视为学习的机会(逻辑赚取的简写=赚取逻辑)。毕竟,这就是Prolog,它的意思是逻辑编程。那么程序中的逻辑在哪里?
目前您的程序失败了,但是您希望它能够成功。罪魁祸首在哪里?让我们一般化您的程序,以使生成的程序仍然失败,但是要小得多。概括程序的两种简单方法:
删除目标(通过添加前缀*
)
删除条款(将term
替换为_
/*term*/
我们可以很盲目的做到这一点。无需了解您的程序。只需重新检查目标仍然失败即可。这是我第一次尝试时想到的:
:- op(950, fy, *). * _G_0. % ignore the argument _G_0 sum([], _/*0*/). sum([_/*[_,Head]*/|[_,Tail]], Sum) :- *sum([_,Tail], Sum2), *Sum is Head+Sum2. ?- sum([_/*[a, 1]*/, _/*[b, 2]*/, _/*[c, 3]*/, _/*[d, 4]*/], Total). false. % gnah - still fails
一个问题必须存在于其余可见部分。太难弄清楚了吗?让Prolog通过查询最普遍的查询:
向您解释| ?- sum(Xs, Sum).
Xs = []
; Xs = [_A,_B,_C].
因此,只能有两个长度的列表:空列表和包含三个元素的列表。请注意,我们目前有谓词的通用版本。因此,不能保证我们会找到两种长度的解决方案。但是,我们可以100%确保所有其他长度都没有解决方案。
让我们回到原始程序并询问最普遍的查询:
?- sum(Os, Total).
Os = [], Total = 0
; false.
Oh no,只有一个解决方案。甚至没有sum([_|_], Total)
的单一解决方案。
所以让我们再次概括该程序,但现在针对这个失败的目标:
sum([], _/*0*/). sum([_/*[_,Head]*/|[_,Tail|_/*[]*/]], Sum) :- sum([_,Tail], Sum2), *Sum is Head+Sum2. ?- Os = [_|_], sum(Os, Total). false.
在此部分中,必须进一步存在错误。实际上,目标sum([_,Tail], Sum2)
是罪魁祸首:它是关于一列恰好两个元素的列表,但是该规则至少要包含三个
有关实际的修补程序,请参见其他答案。
此方法适用于纯单调的程序,例如您的程序。