简体   繁体   English

如何在Prolog中递归计数和求和

[英]How to count and sum recursively in Prolog

I'm trying to figure out how to use recursion on count and sum rules.我试图弄清楚如何在计数和求和规则上使用递归。

I usually do it with lists, using findall and length or findall and sum_list, but I'm not sure if that's my best option on all cases.我通常使用列表,使用 findall 和 length 或 findall 和 sum_list,但我不确定这是否是所有情况下的最佳选择。

This is my approach with lists:这是我的列表方法:

%person(name, surname, age)
person('A', 'H', 22).
person('B', 'G', 24).
person('C', 'F', 20).
person('D', 'E', 44).
person('E', 'D', 45).
person('F', 'C', 51).
person('G', 'B', 40).
person('H', 'A', 51).

count_person(Total_count) :-           % rule to count how many person are.
   findall(N, person(N, _, _), List),
   length(List, Total_count).

sum_ages(Total_sum) :-                 % rule to sum all the ages.

   findall(Age, person(_, _, Age), List),
   sum_list(List, Total_sum).

or here: https://swish.swi-prolog.org/p/cswl.pl或在这里: https : //swish.swi-prolog.org/p/cswl.pl

How should I do this using recursion?我应该如何使用递归来做到这一点?

I do not have an elegant solution.我没有一个优雅的解决方案。 But with retract and assert you can control the recursion:但是使用retractassert你可以控制递归:

:- dynamic([person/3,person1/3]).

count_person(N) :-
    count_person(0,N).

count_person(Acc,N) :-
    retract(person(A,B,C)),
    !,
    assert(person1(A,B,C)),
    N1 is Acc+1,
    count_person(N1,N).
count_person(N,N) :-
    clean_db.

clean_db :-
    retract(person1(A,B,C)),
    assert(person(A,B,C)),
    fail.
clean_db.

You should take a look at library( aggregate ).你应该看看 library( aggregate )。

For instance:例如:

count_person(Total_count) :-
  aggregate(count, A^B^C^person(A,B,C), Total_count).

or the simpler form (try to understand the difference, it's aa good way to learn the basic about variables quantification )或者更简单的形式(尝试理解差异,这是学习变量量化基础的好方法)

count_person(Total_count) :-
  aggregate_all(count, person(_,_,_), Total_count).

The library has grown out of the necessity to simplify the implementation of typical aggregation functions available in SQL (since Prolog is relational at heart):该库的发展是为了简化 SQL 中可用的典型聚合函数的实现(因为 Prolog 是关系型的):

sum_ages(Total_sum) :-
  aggregate(sum(Age), A^B^person(A,B,Age), Total_sum).

You can also get combined aggregates in a step.您还可以在一个步骤中获得组合聚合。 Average is readily implemented:平均值很容易实现:

ave_ages(Ave) :- 
  aggregate(t(count,sum(Age)), A^B^person(A,B,Age), t(Count,Sum)), Ave is Sum/Count.

If you implement using count_person/1 and sum_ages/1 the interpreter would scan twice the goal...如果您使用 count_person/1 和 sum_ages/1 实现,解释器将扫描目标的两倍......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM