2017-10-20 52 views
2

我想弄清楚如何在count和sum規則上使用遞歸。如何在Prolog中遞歸計數和求和

我通常用list,findall和length或findall和sum_list來做,但我不確定這是否是我所有情況下的最佳選擇。

這是我的做法與列表:

%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). 

或在這裏:https://swish.swi-prolog.org/p/cswl.pl

我應該怎麼做這個使用遞歸?

回答

1

你應該看一看庫(aggregate)。

例如:

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

或簡單的形式(嘗試理解上的差異,這是學習基本的有關變量的AA好辦法量化

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

圖書館已經成長出於簡化SQL中典型聚合函數的實現的必要性(因爲Prolog是關係型的):

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

您還可以在一個步驟中獲得組合聚合。一般容易實現:

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

如果要實現使用count_person/1和sum_ages/1的解釋將掃描兩次目標...

1

我沒有一個優雅的解決方案。但隨着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.