% UItwerking HerTentamen Programmeren in Prolog % Maandag 19 Augustus 2002 % Joris Hulstijn % SCORE: I: 10 + 15 + 5, II:, III:, IV: +10 EXTRA % Opgave I: Kennisrepresentatie % A. /* Weersverwachting ::= weer( Datum :: DatumType, <== sleutel ZonKans :: Percentage [0..100], NeerslagKans :: Percentage [0 .. 100], MinimumTemperatuur :: Graden Celsius [ -50, 70 ] MiddagTemperatuur :: Graden Celsius [ -50, 70 ] Windrichting :: in { N,O,Z,W,NO,NW,ZO,ZW } Windkracht :: Beaufort [ 0 .. 12 ] ) DatumType ::= datum( WeekDag :: { ma, di, wo, do, vr, za, zo }, Dag :: [ 1 .. 31 ], Maand :: { jan, feb ... dec } of [ 1 .. 12 ] Jaar :: [ 1600 .. 3000 ] ) */ weer( datum(di, 16, juli, 2002), 50, 50, 15, 23, 'N', 4). weer( datum(wo, 17, juli, 2002), 30, 30, 15, 22, 'N', 4). weer( datum(do, 18, juli, 2002), 30, 50, 13, 20, 'N', 2). weer( datum(vr, 19, juli, 2002), 30, 30, 13, 20, 'NW', 3). weer( datum(za, 20, juli, 2002), 30, 40, 12, 19, 'W', 4). % 1. Uit welke richting komt de wind op vrijdag? windrichting( Datum, Richting) :- weer( Datum, _, _, _, _, Richting, _). % ?- windrichting( datum(vr, _,_,_), Richting). % 2. Op welke dag wordt het het warmst? middagtemp( Datum, Temp) :- weer( Datum, _, _, _, Temp, _, _ ). % ?- findall( T:D, middagtemp(D, T), TDs ), % max(TDs, -50:nooit, Dag). max([], _Max:Dag, Dag). max([T:D|Rest], MaxTotNu:_DagTotNu, Dag) :- T > MaxTotNu, !, % groen max(Rest, T:D, Dag). max([T:_D|Rest], MaxTotNu:DagTotNu, Dag) :- T =< MaxTotNu, max(Rest, MaxTotNu:DagTotNu, Dag). % 3. Op welke dagen waait het matig (windkracht 3 of 4)? windkracht( Datum, Wind) :- weer( Datum, _, _, _, _, _, Wind). % ?- findall( Dag, ( windkracht(Dag, 3);windkracht(Dag, 4) ), Dagen ). % 4. Op hoeveel dagen is de kans op zon kleiner dan 50 \%? zon( Datum, ZonKans) :- weer( Datum, ZonKans, _, _, _, _, _). % ?- findall( Dag, (zon(Dag, Kans), Kans < 50), Dagen), % length(Dagen, Hoeveel). % 5. Wat is de gemiddelde minimumtemperatuur voor deze periode van 5 dagen? % ?- findall( T, middagtemp(_Dag, T), Ts), gemiddelde(Ts, GemT). som([], 0). som([H|T], Som) :- som(T, S), Som is S+H. gemiddelde( L, Gem) :- som(L, Som), length(L, N), Gem is Som/N. % C. % 1. Een dag is {\em zonnig} als de kons op zonneschijn groter is dan 50 \%. zonnig( Dag ) :- zon( Dag, ZonKans) , ZonKans > 50. % 2. Een dag is {\em regenachtig} als de kans op regen groter is dan 50 \%. regenachtig( Dag ) :- neerslag( Dag, NeerslagKans) , NeerslagKans > 50. neerslag( Datum, NeerslagKans) :- weer( Datum, _, NeerslagKans, _, _, _, _ ) . % 3. In de zomer vinden we het {\em redelijk weer}, % als het warmer is dan 20 graden, en het is niet regenachtig. redelijk( Dag) :- middagtemp( Dag, Temp), Temp > 20, \+ regenachtig(Dag). % 4. We vinden het {\em mooi weer}, % als het warmer is dan 20 graden, en het is zonnig. mooi( Dag) :- middagtemp( Dag, Temp), Temp > 20, zonnig(Dag). % ---------------------------------------------------------------------- % II. Cut en Matchen % A1. Ze zijn rood, want als je ze weghaalt, of als je volgorde van de % clauses verandert, dan verandert de betekenis van het predikaat % {\tt class/2}. % A2. % Ja, en nee. Het gaat om exclusieve gevallen. Deze kunnen ook door % gebruik van 'not' worden geimplementeerd. Echter, 'not' is zelf weer % geimplementeerd met een cut. class(X, 'A') :- q(X, good). % regel 2, ! weg class(X, 'B') :- not q(X, good), % mag evt weg q(X, reasonable). % regel 4, ! weg class(X, 'C') :- not q(X, good) , not q(X, reasonable). % B. Definitie Matching match(S,T) :- % geval 1: S en T zijn beide constant (atomic) constant(S), % dwz getal of atom constant(T), % dan moet S == T (identiek) S == T. match(S,T) :- % geval 2: S of T is een variabele var(S), % dan wordt substitutie S/T of T/S toegevoegd S = T. match(S,T) :- var(T), T = S. match(S,T) :- % geval 3: S en T zijn samengesteld S =.. [FunctorS| ArgsS], T =.. [FunctorT| ArgsT], FunctorS == FunctorT, match(ArgsS,ArgsT). % dan moet de functor identiek zijn % en moeten de argumenten ook matchen (recursie) % ------------------------------------------------------------------------ % III. Lijsten % 10 pt % A. splits(+L, -Klinkewrs, -Medeklinkers) splits([],[],[]). splits([C|Cs], [C|Klinkers], Medeklinkers) :- klinker(C),!, splits(Cs, Klinkers, Medeklinkers). splits([C|Cs], Klinkers, [C|Medeklinkers]) :- splits(Cs, Klinkers, Medeklinkers). klinker(C) :- member(C, "EUIOAeuioa"). % B. schrijf(0, _Char). schrijf(N, Char) :- N >= 0, !, write(Char), M is N-1, schrijf(M, Char). % piramide(+Basis) % schrijft omgekeerde piramide met een Basis % PRE: Basis is oneven. piramide(Basis) :- Diepte is ((Basis-1)/2)+1, loop(Diepte, 0, Basis). % loop(+Diepte, +Wit, +Basis) loop(0, _W, _B). loop(D, W, B) :- schrijf(W, ' '), schrijf(B, '*'),nl, D1 is D - 1, W1 is W + 1, B1 is B - 2, loop(D1, W1, B1). % --------------------------------------------------------------------- % IV. Grammatica s --> np, vp. q --> qw, vp. q --> vp, np. np --> det,n. np --> name. n --> [man]; [vrouw]; [huis]. name --> [jan]; [joris]; [leon]. det --> [de] ; [het]; [een]. qw --> [wie]; [wat]. vp --> v, np. vp --> i_v. v --> [houdt, van]; [slaat]; [woont, in]; [gaat, naar]. i_v --> [loopt]; [zingt]; [is, verliefd]. % A. Er zijn twee verschillen: % -- in vraagzinnen (q) mag een _vraagwoord_ zoals wie, of wat voorkomen, of % -- een vraagzin heeft een andere _volgorde: "loopt jan", ipv "jan loopt". % B. % 1. :- s([de, man, gaat, naar, huis],[]). % No, want "huis" is geen NP. % 2. :- q([wie, gaat, naar, het, vrouw],[]). % Yes, /* q / \ qw vp | / \ | v np wie | / \ gaat naar det n | | het vrouw */ % 3. :- q([woont, in, leon, joris],[]). /* q / \ vp np / \ | v np name | | | woont in name joris | leon */ % 4. :- q([wie, houdt, van, de, vrouw]). % No, Undefined predicate: `q/1' ; Rest difference list ontrbeekt % 5. :- s([de, man, zingt, het, huis],[het, huis]). % Yes, /* De rest van de zin ([het,huis]) wordt niet geparseerd. Dit heeft te maken met de difference-list constructie. s / \ np vp / \ | det n i_v | | | de man zingt */ % B. % Pas de regels als volgt aan. np --> det(Geslacht),n(Geslacht). np --> name. n(mv) --> [man]; [vrouw]. n(onz) --> [huis]. name --> [jan]; [joris]; [leon]. det(mv) --> [de]. det(onz) --> [het]. det(_) --> [een].