2017-10-20 14 views
2

カウントとサムルールで再帰を使用する方法を理解しようとしています。Prologで再帰的にカウントして合計する方法

私は通常、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). 

または単純な形式のライブラリが成長してきました

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

(違いを理解しようとするが、それは変数に関する基本を学ぶためのAAの良い方法定量です) 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. 
関連する問題