Declaratieve Talen/oplossingenContradicties: verschil tussen versies
Naar navigatie springen
Naar zoeken springen
Nieuwe pagina aangemaakt met '% To dO een predicaat meetegen(P,A) schrijven dat teruggeeft of die % antwoordletter in contradictie is met een andere antwordleter. % In een graaf ziet een contradict…' |
Oplossing toegevoegt |
||
(7 tussenliggende versies door 3 gebruikers niet weergegeven) | |||
Regel 1: | Regel 1: | ||
% To | <pre> | ||
% To Do een predicaat meetegen(P,A) schrijven dat teruggeeft of die | |||
% antwoordletter in contradictie is met een andere antwordleter. | % antwoordletter in contradictie is met een andere antwordleter. | ||
% In een graaf ziet een contradictie eruit indien er een lus is. | % In een graaf ziet een contradictie eruit indien er een lus is. | ||
Regel 32: | Regel 33: | ||
tegen(P,Tegens):- findall(X,doorloopGraaf(P,X,X,[]),Tegens). | tegen(P,Tegens):- findall(X,doorloopGraaf(P,X,X,[]),Tegens). | ||
</pre> | |||
--[[Gebruiker:Greet|Greet]] | |||
Alternatief omdat ik denk dat bovenstaande over het algemeen niet werkt: | |||
<pre> | |||
% Prolog-feiten | |||
antwoord(jan,c,[a,b,d,e]). | |||
antwoord(jan,i,[f,k,c,b]). | |||
antwoord(jan,j,[i,f,h,e]). | |||
antwoord(jan,k,[j,h,g,d]). | |||
% Atoom voor een quick-and-dirty manier om de recursie | |||
% van pad/6 te laten eindigen. | |||
pad_gevonden. | |||
% A is in contradictie met een andere letter | |||
% als er een kring bestaat die begint in A | |||
meetegen(P,A) :- | |||
pad(P,A,A,A,[],_). | |||
% bouw eerst alle lijsten op van letters die in contradictie zijn met elkaar | |||
% en verwijder dan alle dubbels die zijn ontstaan | |||
tegen(P,Tegens) :- | |||
findall(Letter, antwoord(P,Letter,_), LetterLijst), | |||
findall(Pad, (member(X,LetterLijst), langste_pad(P,X,Pad)), Paden), | |||
sortlists(Paden,DeepLevelSorted), | |||
sort(DeepLevelSorted,Tegens). % verwijdert duplicates | |||
% sorteer een lijst van lijsten | |||
sortlists(In,Out) :- sortlists(In,[],Out). | |||
sortlists([],Out,Out). | |||
sortlists([In | Rest],Acc,Out) :- | |||
sort(In,Sorted), | |||
NewAcc = [ Sorted | Acc ], | |||
sortlists(Rest,NewAcc,Out). | |||
% Voor Persoon is Y een buur van letter als Y voorkomt in de lijst voor die letter | |||
% en als Y ook een onderdeel is van een antwoord/3 feit. | |||
% Volgens deze logica is 'j' een buur van 'i', maar is 'e' geen buur van 'c' | |||
buren(Persoon,Letter,Y) :- | |||
antwoord(Persoon,Letter,Lijst), | |||
member(Y,Lijst), | |||
antwoord(Persoon,Y,_). | |||
% Er is een pad gevonden: output Pad | |||
pad(_,_,_,_,pad_gevonden,Pad,Pad). | |||
pad(Persoon,Bron,Doel,Vorige,Acc,Bezocht) :- | |||
buren(Persoon,Vorige,Y), % backtracking zorgt ervoor dat effectief alle buren worden overlopen | |||
\+ member(Y,Acc), % anders loopt Prolog vast in een kring | |||
(Doel == Y -> % pad gevonden: output deze | |||
reverse([ Y | Acc ],NewAcc), | |||
pad(Persoon,Bron,Doel,Y,pad_gevonden,NewAcc,Bezocht) | |||
; | |||
NewAcc = [ Y | Acc ], | |||
pad(Persoon,Bron,Doel,Y,NewAcc,Bezocht)). | |||
% vindt het langste pad voor de gegeven letter | |||
langste_pad(P,Letter,Pad) :- | |||
findall(Pad, pad(P,Letter,Letter,Letter,[],Pad), Paden), | |||
langste_rec(Paden,0,Acc,Pad). | |||
langste_rec([], _, Langste, Langste). | |||
langste_rec([Pad | Paden],Length,Acc,Langste) :- | |||
length(Pad,CurrLength), | |||
(CurrLength > Length -> | |||
NewAcc = Pad, | |||
langste_rec(Paden,CurrLength,NewAcc,Langste) | |||
; | |||
langste_rec(Paden,Length,Acc,Langste)). | |||
</pre> | |||
--[[Gebruiker:Thomas Vochten|Thomas Vochten]] | |||
<pre> | |||
antwoord(jan,c,[a,b,d,e]). | |||
antwoord(jan,i,[f,k,c,b]). | |||
antwoord(jan,j,[i,f,h,e]). | |||
antwoord(jan,k,[j,h,g,d]). | |||
meetegen(P,A) :- | |||
meetegen(P,A,A,[],_). | |||
% Persoon, huidig uitbreid punt, te zoeken antwoord, reeds bezochte | |||
% punten, de lus | |||
meetegen(_,_,A,Acc,Loop) :- | |||
member(A,Acc), % Antwoord heeft zichzelf gevonden | |||
sort(Acc,Loop),!. % Mooi alfabetisch, helpt bij het tegen predikaat | |||
meetegen(P,Aa,A,Acc,Loop) :- | |||
antwoord(P,Aa,Pref), % Neem de voorkeuren van het huidig antwoord | |||
findall(M, (member(M,Pref), \+ member(M,Acc)), Ms), % Elk nog niet reeds bezocht punt | |||
member(Mx,Ms), % Minstens eentje is genoeg om een loop te vinden | |||
meetegen(P,Mx,A,[Mx|Acc],Loop). % Zoek verder in elk van die punten | |||
% Luie aanpak: zoek elke mogelijkheid, dus de lus [i,j,k] word op 3 | |||
% verschillende manieren gevonden. Daarna filteren we ze gewoon weg. | |||
tegen(P,Tegens) :- | |||
findall(Loop,meetegen(P,A,A,[],Loop),TegensList), | |||
list_to_set(TegensList,Tegens). | |||
</pre> | |||
--[[Gebruiker:Brecht Derwael|Brecht Derwael]] |
Huidige versie van 13 jan 2016 12:31
% To Do een predicaat meetegen(P,A) schrijven dat teruggeeft of die % antwoordletter in contradictie is met een andere antwordleter. % In een graaf ziet een contradictie eruit indien er een lus is. % Algemene Strategie : we gaan voor de gegeven antwoordletter het pad % doorheen de graaf volgen en kijken of we een pad naar onszelf tegen % komen %Prolog feiten: antwoord(jan,c,[a,b,d,e]). antwoord(jan,i,[f,k,c,b]). antwoord(jan,j,[i,f,h,e]). antwoord(jan,k,[j,h,g,d]). buren(X,Y):-antwoord(_,X,Lijst), member(Y,Lijst). % buren in de andere richting zou je hier ook makkelijk kunnen % definieren, maar dit is in ons geval niet nodig. meetegen(P,A):-antwoord(P,A,_), doorloopGraaf(P,A,A,[A]),!. doorloopGraaf(P,A,B,Pad):- buren(A,X), ( \+ member(X,Pad)-> append(Pad,[X],New), doorloopGraaf(P,X,B,New) ; true ). %maak een predikaat tegen(P,Tegens) tegen(P,Tegens):- findall(X,doorloopGraaf(P,X,X,[]),Tegens).
--Greet
Alternatief omdat ik denk dat bovenstaande over het algemeen niet werkt:
% Prolog-feiten antwoord(jan,c,[a,b,d,e]). antwoord(jan,i,[f,k,c,b]). antwoord(jan,j,[i,f,h,e]). antwoord(jan,k,[j,h,g,d]). % Atoom voor een quick-and-dirty manier om de recursie % van pad/6 te laten eindigen. pad_gevonden. % A is in contradictie met een andere letter % als er een kring bestaat die begint in A meetegen(P,A) :- pad(P,A,A,A,[],_). % bouw eerst alle lijsten op van letters die in contradictie zijn met elkaar % en verwijder dan alle dubbels die zijn ontstaan tegen(P,Tegens) :- findall(Letter, antwoord(P,Letter,_), LetterLijst), findall(Pad, (member(X,LetterLijst), langste_pad(P,X,Pad)), Paden), sortlists(Paden,DeepLevelSorted), sort(DeepLevelSorted,Tegens). % verwijdert duplicates % sorteer een lijst van lijsten sortlists(In,Out) :- sortlists(In,[],Out). sortlists([],Out,Out). sortlists([In | Rest],Acc,Out) :- sort(In,Sorted), NewAcc = [ Sorted | Acc ], sortlists(Rest,NewAcc,Out). % Voor Persoon is Y een buur van letter als Y voorkomt in de lijst voor die letter % en als Y ook een onderdeel is van een antwoord/3 feit. % Volgens deze logica is 'j' een buur van 'i', maar is 'e' geen buur van 'c' buren(Persoon,Letter,Y) :- antwoord(Persoon,Letter,Lijst), member(Y,Lijst), antwoord(Persoon,Y,_). % Er is een pad gevonden: output Pad pad(_,_,_,_,pad_gevonden,Pad,Pad). pad(Persoon,Bron,Doel,Vorige,Acc,Bezocht) :- buren(Persoon,Vorige,Y), % backtracking zorgt ervoor dat effectief alle buren worden overlopen \+ member(Y,Acc), % anders loopt Prolog vast in een kring (Doel == Y -> % pad gevonden: output deze reverse([ Y | Acc ],NewAcc), pad(Persoon,Bron,Doel,Y,pad_gevonden,NewAcc,Bezocht) ; NewAcc = [ Y | Acc ], pad(Persoon,Bron,Doel,Y,NewAcc,Bezocht)). % vindt het langste pad voor de gegeven letter langste_pad(P,Letter,Pad) :- findall(Pad, pad(P,Letter,Letter,Letter,[],Pad), Paden), langste_rec(Paden,0,Acc,Pad). langste_rec([], _, Langste, Langste). langste_rec([Pad | Paden],Length,Acc,Langste) :- length(Pad,CurrLength), (CurrLength > Length -> NewAcc = Pad, langste_rec(Paden,CurrLength,NewAcc,Langste) ; langste_rec(Paden,Length,Acc,Langste)).
antwoord(jan,c,[a,b,d,e]). antwoord(jan,i,[f,k,c,b]). antwoord(jan,j,[i,f,h,e]). antwoord(jan,k,[j,h,g,d]). meetegen(P,A) :- meetegen(P,A,A,[],_). % Persoon, huidig uitbreid punt, te zoeken antwoord, reeds bezochte % punten, de lus meetegen(_,_,A,Acc,Loop) :- member(A,Acc), % Antwoord heeft zichzelf gevonden sort(Acc,Loop),!. % Mooi alfabetisch, helpt bij het tegen predikaat meetegen(P,Aa,A,Acc,Loop) :- antwoord(P,Aa,Pref), % Neem de voorkeuren van het huidig antwoord findall(M, (member(M,Pref), \+ member(M,Acc)), Ms), % Elk nog niet reeds bezocht punt member(Mx,Ms), % Minstens eentje is genoeg om een loop te vinden meetegen(P,Mx,A,[Mx|Acc],Loop). % Zoek verder in elk van die punten % Luie aanpak: zoek elke mogelijkheid, dus de lus [i,j,k] word op 3 % verschillende manieren gevonden. Daarna filteren we ze gewoon weg. tegen(P,Tegens) :- findall(Loop,meetegen(P,A,A,[],Loop),TegensList), list_to_set(TegensList,Tegens).