问题
I want to modify the code on Creating a list from user input with swi-prolog :
diagnose(Disease):-
retractall(symptom(_)),
getSymptoms(List),
forall(member(X,List),assertz(symptom(X))),
disease(Disease).
getSymptoms([Symptom|List]):-
writeln('Enter Symptom:'),
read(Symptom),
dif(Symptom,stop),
getSymptoms(List).
getSymptoms([]).
disease(flu):-
symptom(fever),
symptom(chills),
symptom(nausea).
disease(cold):-
symptom(cough),
symptom(runny_nose),
symptom(sore_throat).
disease(hungover):-
symptom(head_ache),
symptom(nausea),
symptom(fatigue).
If I enter 3 symptoms: cough, nausea, fatigue, I should get output of number of symptoms present for different diseases, e.g.:
flu: 1
cold: 1
hungover: 2
How can I get this in Prolog? I know SWI-Prolog has an intersection function that can be used, but how exactly to apply it here?
?- intersection([fever, chills, nausea] ,[cough, nausea, fatigue], X).
X = [nausea].
回答1:
I don't think the way the data is represented in the linked answer is the best approach to representing such data. It's best to render the data as individual facts which is much more versatile. Thus, for example, the following is inflexible and obscures the individual symptom relationships:
disease(flu):-
symptom(fever),
symptom(chills),
symptom(nausea).
The individual symptoms could be extracted using clause/2
, as clause(disease(flu), Symptoms)
would yield, Symptoms = (symptom(fever), symptom(chills), symptom(nausea))
and then the individual symptoms can be extracted from there.
I think it's clearer, however, to represent it as:
illness_symptom(flu, chills).
illness_symptom(flu, nausea).
illness_symptom(flu, fever).
If you want to collect the symptoms of a given illness into a list, you just use findall/3
:
illness_symptoms(Illness, Symptoms) :-
findall(Symptom, illness_symptom(Illness, Symptom), Symptoms).
Calling illness_symptoms(flu, Symptoms)
would yield, Symptoms = [chills, nausea, fever]
.
来源:https://stackoverflow.com/questions/38136163/getting-number-of-common-items-between-lists-in-prolog