Help with simple prolog exercise
I haven't been able to solve this prolog exercise. I was hoping someone here could give me some hints or post a solution. Thanks in advance.
Database:
lig(super, porto).
lig(super, benfica).
lig(super, sporting).
lig(honra, feirense).
lig(honra, guimaraes).
jog(sporting, ricardo, gr).
jog(guimaraes, cleber, de).
jog(feirense, edgar, me).
jog(porto, quaresma, av).
jog(porto, helton, gr).
jog(benfica, simao, av).
jog(sporting, moutinho, me).
The sample output:
?- calcula(Lista).
Lista = [super-[porto-[quaresma,helton], benfica-[simao], sporting-
[mout开发者_如何学Pythoninho,ricardo]], honra-[ feirense-[edgar], guimarães-[cleber]]].
My procedure:
calcula(Lista) :-
findall(Lig-[Eq-[X]],
(lig(Lig, Eq), findall(Jog, jog(Eq, Jog, _), X)),
Lista).
My output (which is wrong!).
Lista = [super-[porto-[[quaresma, helton]]], super-[benfica-[[simao]]], super-[sporting-[[ricardo, moutinho]]], honra-[feirense-[[edgar]]]
I see in the zfm's solution, the predicate lig(Lig, _)
becomes true 5 times so there is some duplication in the final list. You can use the predicate setof/3
and existential quantified variable Eq0^
to remove duplication:
calcula(T) :- setof(Lig-X, Eq0^(lig(Lig, Eq0),
findall(Eq-U, (lig(Lig,Eq), findall(Jog, jog(Eq, Jog, _), U)), X)), T).
Since I'm so interested to the question, I try it a lot.
Well, this is, I believe, not the best answer. However I get the result.
calcula(Ans):-findall(Lig-X, (lig(Lig, _),
findall(Eq-U, (lig(Lig,Eq), findall(Jog, jog(Eq, Jog, _), U)), X)), T),
removeEq(T,Ans).
removeEq([A-B,A-_|Tail], [A-B|TailChanged]) :- !, removeEq([A-B|Tail],
[A-B|TailChanged]).
removeEq([A-B,C-D|Tail], [A-B,C-D|TailChanged]) :- removeEq([A-B|Tail],
[A-B|TailTemp]), removeEq([C-D|TailTemp], [C-D|TailChanged]).
removeEq([X], [X]).
The removeEq
is needed because there are duplicated answer (I don't know how not to duplicate it)
This is not shorter than zfm's answer, but it is "simpler" in the way that it only uses basic prolog constructs to construct the list directly. (No removal of duplicates afterward.) There is some code duplication which probably could be gotten rid of to get a shorter answer.
g(Second, [Third|Rest], Done) :- jog(Second, Third,_),
not(member(Third, Done)),!,
g(Second, Rest, [Third|Done]).
g(_,[],_).
f(First, [Second-New|Rest], Done) :- lig(First, Second),
not(member(Second, Done)),!,
g(Second, New, []),
f(First, Rest, [Second|Done]).
f(_,[],_).
h([First-X|Lista], Done):-
lig(First,_),
not(member(First, Done)),!,
f(First, X, []),
h(Lista,[First|Done]).
h([], _).
calcula(X) :- h(X, []).
精彩评论