%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.
How can you add elements to a list or compute them from the knowledge base without using findall or assert/retract in Prolog?
-
10-03-2022 - |
Question
I have a knowledge base that consists of students database in a file 'students.pl' like this:
% 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]).
I want to access each student predicate from the knowledge base and calculate the average marks in each subject or average percentage, without using 'findall' or assert/retract. I may want to use backtracking like this:
find_score_all(X) :- student(Name,Percent,L),
write(Percent),nl,
fail.
find_score_all(_).
With this approach I can access each element and write it, but if I want to add each 'Percent' value as an element to a list or just use a predicate like 'Percent1 is Total + Percent' to total the percent values and then find its average, how can I do so? Note that I dont want to use findall or retract/assert and preferably find the average in one pass through the knowledge base since the knowledge base is very large.
Any help is appreciated.
No correct solution
OTHER TIPS
if you want to add to a list then you should use findall, or better, library(aggregate). But if you fear about efficiency, you could use something like this
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(+, :, ?).
test:
members(X) :- member(X, [1,2,3,4]).
?- integrate(ave, members, R).
R = 2.5 .
Of course, you'll need to add error handling (at least, when counter C == 0
).