目前正在学习计算逻辑以及Prolog的基础知识。在我的笨拙演讲中请耐心等待我!
我遇到过一个问题,在查询包含整数的列表列表时,必须设计一种方法来计算使用递归计算所有列表的最高总和。
例如:
?- getSum([[1,3,6],[9,5,2],[3,4,7]], X).
X = 16.
应该是输出。
我相信找到列表总和的正确方法是:
sum([],0).
sum([Head|Body], Output) :- sum(Body, BodySum),
Output is Head + BodySum.
但是我需要在显示结果之前比较总和,我是否必须在总和递归中调用另一个条件?
由于
答案 0 :(得分:4)
首先发表几条评论:
命名:您可能希望为谓词命名,以便明确它的作用。并且,Prolog更喜欢names_like_this
到namesInCamelCase
。也许,可以称之为max_sublist_sum
,也许?
实施:在您提出的问题中,"使用递归"。 必须你使用递归,还是认为使用递归是你唯一的选择?由于这是一个微不足道的问题,因此可以使用库谓词并完全避免递归来解决它。例如,要查找每个子列表的总和:
maplist(sum_list, List_of_lists, Sums)
现在,您已将列表列表缩减为总和列表。您可以找到最大的数字列表:
max_list(List_of_numbers, Max_number)
所以,你的问题变成了:
?- maplist(sum_list, [[1,3,6],[9,5,2],[3,4,7]], Sums),
max_list(Sums, Max_sum).
Sums = [10, 16, 14],
Max_sum = 16.
现在,实施sum_list/2
和max_list/2
中的每一个似乎都是一个很好的练习,但一个好的起点是查看这两个中的library implementation。同样适用于definition of maplist/3
你也可以将两者交织在一起:
max_sublist_sum0([H|T], Max) :- sum_list(H, Sum), max_sublist_sum0_(T, Sum, Max). max_sublist_sum0_([], Max, Max). max_sublist_sum0_([H|T], M0, Max) :- sum_list(H, Sum), ( Sum > M0 -> max_sublist_sum0_(T, Sum, Max) ; max_sublist_sum0_(T, M0, Max) ).
辅助谓词max_sublist_sum_/3
实际上是一个折叠:
max_sum(L, M0, M) :- sum_list(L, Sum), M is max(M0, Sum). max_sublist_sum1([H|T], Max) :- sum_list(H, Sum), foldl(max_sum, T, Sum, Max).
然而,这仍然是比原始建议更多的代码:
max_sublist_sum(L, M) :- maplist(list_sum, L, S), max_list(S, M).
有趣的是,在我的计算机上,最后一个版本对于较大的列表也是最快的,并且与其他两个版本的速度相同。
答案 1 :(得分:-1)
您不需要在递归中调用另一个条件,您必须将问题分解为计算总和和最大值。遵循max
谓词的经典实现,其中第二个参数是当前最大值,这将类似于:
max([], X, X).
max([H|T], X, Y) :-
sum(H, S),
S < X,
max(T, X, Y).
max([H|T], X, Y) :-
sum(H, S),
S >= X,
max(T, S, Y).
getSum(L, X) :- max(L, 0, X).
通过使用if-construct或cut,你可以使这段代码更有效率和优雅,我把它留给你。