Declaratieve Talen/Oplossing celautomaat: verschil tussen versies

Uit Wina Examenwiki
Naar navigatie springen Naar zoeken springen
Roald (overleg | bijdragen)
Geen bewerkingssamenvatting
Nick.dewaele (overleg | bijdragen)
nog een oplossing
 
Regel 86: Regel 86:
  regels(Seqs, RegelAcc, Regels).
  regels(Seqs, RegelAcc, Regels).
[[Gebruiker:Roald|Roald]] 12 jan 2010 22:38 (UTC)
[[Gebruiker:Roald|Roald]] 12 jan 2010 22:38 (UTC)
=== Nog een oplossing ===
--[[Gebruiker:Nick.dewaele|Nick.dewaele]] ([[Overleg gebruiker:Nick.dewaele|overleg]]) 30 dec 2017 19:01 (CET)
<strong>Deze is gebaseerd op het gedeeltelijk instantieren van de kop van een lijst (wordt wel duidelijk als je de debugger volgt)</strong>
<code>
exampleRules(R) :- R = [[o,o,o,o],[o,o,x,x], [o,x,o,o], [x,o,o,x], [x,o,x,x]].
% past een regel toe, gegeven een lijst regels. Res unificeert met het nieuwe symbool,
% en AppliedRule is de regel die toegepast werd
applyAppropRule(A,B,C,[[A,B,C,D]|_], D, [A,B,C,D]).
applyAppropRule(A,B,C,[[X,Y,Z,_]|Tail], Res, AppliedRule) :-
        A-B-C \= X-Y-Z,
        applyAppropRule(A,B,C,Tail, Res, AppliedRule).
% zoals gevraagd in de opgave
volgendegen(Seq, Rules, Res) :-
        nextLevel(Seq, Rules, Res, _).
% hulppredicaat voor 'volgendegen'. Deze zal zowel het resultaat teruggeven als de lijst van toegepaste regels (belangrijk voor het tweede deel)
nextLevel(Seq, Rules, Res, AppliedRules) :-
        append([o,o|Seq], [o,o], Seq2),
        length(Seq, L),
        LenRes is L + 2,
        length(Res, LenRes),
        subs(Seq2, Rules, [], Res, [], AppliedRules).
% voer 1 substitutie uit, waarbij je het resultaat Res 1 stapje verder instantieert.
% Dit geeft ook een lijst van toegepaste regels.
subs([A,B,C|T], Rules, Acc, Res, AccRules, AppliedRules) :-
        applyAppropRule(A,B,C,Rules, NewSymbol, AppliedRule),
        append(Acc,[NewSymbol], NewAcc),
        append(NewAcc, _, Res),
        subs([B,C|T], Rules, NewAcc, Res, [AppliedRule | AccRules], AppliedRules).
subs(L, _, _, _, AccRules, AccRules) :-
        L \= [_,_,_|_].       
% zoals gevraagd in de opgave
regels(L, Rules) :-
        search(L, <nowiki>[[o,o,o,o]]</nowiki>, UsedRules),
        sort(UsedRules, Rules).
% hulppredicaat voor 'regels'. AccRules geeft de regels die tot nu toe gebruikt zijn.
search([Seq,Seq2|Seqs], AccRules, FinalRules) :-
        append(AccRules, _, Rules),
        nextLevel(Seq, Rules, Seq2, ApplRules),
        append(AccRules, ApplRules, NewRules),
        search([Seq2|Seqs], NewRules, FinalRules).
       
search([_], AccRules, AccRules).
</code>

Huidige versie van 30 dec 2017 18:01

Een oplossing

Deze oplossing werkte voor zover ik getest heb... Bij predicaat regels wordt ook overal de 'javelregel' toegevoegd.

volgendegen(Seq,Regels,Volgende):-
	volgendegen2([o,o|Seq],Regels,Volgende).

volgendegen2([S1,S2],Regels,[V1,V2]):-
	member([S1,S2,o,V1],Regels),
	member([S2,o,o,V2],Regels).
volgendegen2([S1,S2,S3|Seq],Regels,[V1|Volgende]):-
	member([S1,S2,S3,V1],Regels),
	volgendegen2([S2,S3|Seq],Regels,Volgende).

regels([S1,S2],Regels):-
	 regelsseq(S1,Regels,S2).
regels([S1,S2|Sequenties],Regels):-
	 regels([S2|Sequenties],R1),
	 regelsseq(S1,R2,S2),
	 merge(R1,R2,R3),
	 remove_doubles(R3,Regels),
	 geldig(Regels).

% regels genereren voor 1 overgang van een sequentie naar zijn opvolger 
% bij eerste in sequentie 2 o's toevoegen voor het genereren begint
regelsseq(S1,Regels,S2):-
	 regelsseq2([o,o|S1],Regels,S2).

% op het einde van de sequentie 2 extra o's veronderstellen 
regelsseq2([o,o],[ [o,o,o,V] ],[V,V]).
regelsseq2([o,x],[[o,x,o,V1],[x,o,o,V2]],[V1,V2]).
regelsseq2([x,o],[[x,o,o,V1],[o,o,o,V2]],[V1,V2]).
regelsseq2([x,x],[[x,x,o,V1],[x,o,o,V2]],[V1,V2]).
regelsseq2([S1,S2,S3|Seq],Regels,[V1|Volgende]):-
	 regelsseq2([S2,S3|Seq],Regels,Volgende),
	 member([S1,S2,S3,V1],Regels).
regelsseq2([S1,S2,S3|Seq],[[S1,S2,S3,V1]|Regels],[V1|Volgende]):-
	 regelsseq2([S2,S3|Seq],Regels,Volgende),
	 \+member([S1,S2,S3,_],Regels).

% dubbels verwijderen uit een lijst van regels
remove_doubles([L],[L]).
remove_doubles([L|List],L2):-
	 remove_doubles(List,L2),
	 member(L,L2).
remove_doubles([L|List],[L|L2]):-
	 remove_doubles(List,L2),
	 \+member(L,L2).

% testen of een lijst van regels geen tegenstrijdige regels bevat
geldig([_]).
geldig([[X,Y,Z,_]|List]):-
	 geldig(List),
	 \+member([X,Y,Z,_],List).


Een andere oplossing

% Vraag 1:
volgendegen(Seq, Regels, Volgende) :-
	append([o,o|Seq],[o,o],Seq2),
	findall(Nieuw,
		(append(_,Skipped,Seq2),append([A,B,C],_,Skipped),
			member([A,B,C,Nieuw],Regels)
		),
		Volgende).

% Vraag 2:
regels(Sequenties, Regels) :-
	findall(Seq2,
		(member(Seq,Sequenties),
			append([o,o|Seq],[o,o],Seq2)
		),
		Padded),
	regels(Padded, [], Regels).
regels([_], Regels, Regels).
regels([[L,X,R|T1], [_,A,N|T2] | Rest], RegelAcc, Regels) :-
	!,
	(member([L,X,R,_], RegelAcc) ->
		forall(member([L,X,R,OudeRegel], RegelAcc),
			N = OudeRegel),	% Is de regel wel consistent?
		regels([[X,R|T1],[A,N|T2]|Rest], RegelAcc, Regels)
	;
		regels([[X,R|T1],[A,N|T2]|Rest], [[L,X,R,N]|RegelAcc], Regels)
	).
regels([_|Seqs], RegelAcc, Regels) :-
	regels(Seqs, RegelAcc, Regels).

Roald 12 jan 2010 22:38 (UTC)

Nog een oplossing

--Nick.dewaele (overleg) 30 dec 2017 19:01 (CET)

Deze is gebaseerd op het gedeeltelijk instantieren van de kop van een lijst (wordt wel duidelijk als je de debugger volgt)

exampleRules(R) :- R = [[o,o,o,o],[o,o,x,x], [o,x,o,o], [x,o,o,x], [x,o,x,x]].

% past een regel toe, gegeven een lijst regels. Res unificeert met het nieuwe symbool,
% en AppliedRule is de regel die toegepast werd
applyAppropRule(A,B,C,[[A,B,C,D]|_], D, [A,B,C,D]).
applyAppropRule(A,B,C,[[X,Y,Z,_]|Tail], Res, AppliedRule) :-
        A-B-C \= X-Y-Z,
        applyAppropRule(A,B,C,Tail, Res, AppliedRule).

% zoals gevraagd in de opgave
volgendegen(Seq, Rules, Res) :-
        nextLevel(Seq, Rules, Res, _).

% hulppredicaat voor 'volgendegen'. Deze zal zowel het resultaat teruggeven als de lijst van toegepaste regels (belangrijk voor het tweede deel)
nextLevel(Seq, Rules, Res, AppliedRules) :-
        append([o,o|Seq], [o,o], Seq2),
        length(Seq, L),
        LenRes is L + 2,
        length(Res, LenRes),
        subs(Seq2, Rules, [], Res, [], AppliedRules).

% voer 1 substitutie uit, waarbij je het resultaat Res 1 stapje verder instantieert. 
% Dit geeft ook een lijst van toegepaste regels.
subs([A,B,C|T], Rules, Acc, Res, AccRules, AppliedRules) :-
        applyAppropRule(A,B,C,Rules, NewSymbol, AppliedRule),
        append(Acc,[NewSymbol], NewAcc),
        append(NewAcc, _, Res),
        subs([B,C|T], Rules, NewAcc, Res, [AppliedRule | AccRules], AppliedRules).

subs(L, _, _, _, AccRules, AccRules) :-
        L \= [_,_,_|_].        

% zoals gevraagd in de opgave
regels(L, Rules) :-
        search(L, [[o,o,o,o]], UsedRules),
        sort(UsedRules, Rules).

% hulppredicaat voor 'regels'. AccRules geeft de regels die tot nu toe gebruikt zijn.
search([Seq,Seq2|Seqs], AccRules, FinalRules) :-
        append(AccRules, _, Rules),
        nextLevel(Seq, Rules, Seq2, ApplRules),
        append(AccRules, ApplRules, NewRules),
        search([Seq2|Seqs], NewRules, FinalRules).
        
search([_], AccRules, AccRules).