2013-02-19 19 views
0

我,在這樣的文件「students.pl」由學生數據庫的知識基礎:如何在Prolog中將元素添加到列表中或者從知識庫中計算它們而不使用findall或assert/retract?

% student(Name,Percent,List_of_Marks_in_3_subjects). 
student('abc',83,[80,80,90]). 
student('pqr',70,[70,60,80]). 
student('xyz',76,[80,70,80]). 

我想從知識庫獲取每個學生謂詞和計算每個科目的平均分或平均百分比,而不使用'findall'或assert/retract。 我可能要使用回溯這樣的:

find_score_all(X) :- student(Name,Percent,L), 
    write(Percent),nl, 
    fail. 
find_score_all(_). 

用這種方法,我可以訪問每一個元素,寫它,但如果我想每個「百分比」的值作爲元素添加到列表或只使用一個例如「百分比1是總數+百分比」來表示總數百分比值,然後找到其平均值,我該怎麼做? 請注意,我不想使用findall或retract/assert,因爲知識庫非常大,所以最好在通過知識庫的一次傳遞中找到平均值。

任何幫助表示讚賞。

+0

你描述的故障驅動循環,但這樣的循環不能從次迭代信息傳遞,除非通過斷言/收回(除非你使用的擴展名,如SWI的全局變量庫)。爲什麼你禁止使用標準做法? – 2013-02-19 04:10:07

+0

您可以將數字ID從1增加到N給數據庫中的每個學生事實嗎? – 2013-02-19 07:23:13

+0

@ j4n-bur53鏈接答案使用assert。這個問題在主題中指出不要使用findall或assert。 – shujin 2016-07-01 11:07:03

回答

-1

如果你想添加到列表中,那麼你應該使用findall或更好的庫(aggregate)。但是,如果你擔心會有效率,你可以使用類似這樣

integrate(ave, Goal, Ave) :- 
    State = state(0, 0, _), 
    repeat, 
    ( call(Goal, V), 
     arg(1, State, C), U is C+1, nb_setarg(1, State, U), 
     arg(2, State, S), T is S+V, nb_setarg(2, State, T), 
     fail 
    ; arg(1, State, C), arg(2, State, S), Ave is S/C 
    ). 

:- meta_predicate integrate(+, :, ?). 

測試:

members(X) :- member(X, [1,2,3,4]). 

?- integrate(ave, members, R). 
R = 2.5 . 

當然,你需要添加錯誤處理(至少,當計數器C == 0)。

0
%solution for sum of percents, you can replace with any other calculation sum_percent predicate. 
listing(student/3, convert_to_list/2, sum_percent, sum_percent/2). 

% student(Name,Percent,List_of_Marks_in_3_subjects). 
student('abc',83,[80,80,90]). 
student('pqr',70,[70,60,80]). 
student('xyz',76,[80,70,80]). 

convert_to_list(X, R):- 
    student(N, P, LM), 
    not(member(st(N, P, LM), X)), 
    convert_to_list([st(N, P, LM)|X], R). 

convert_to_list(X, X). 

sum_percent:- 
    convert_to_list([], X), 
    sum_percent(X, S), 
    write(S). 

sum_percent([], 0). 
sum_percent([st(_,E,_)|T], S):- 
    sum_percent(T, S2), 
    S is E+S2. 
相關問題