UL/FRI/UNI-RI/MOS/Izpiti/2006-06-08-prolog
Iz E-študij, proste zakladnice študentskega znanja
|
Izpit z dne Napaka: neveljaven čas
Čas pisanja: ni podatka glej podobne izpite minut.
|
Mrzlica pred prihajajočim svetovnim prvenstvom narašča. Pobiralce stav zanima forma posameznih ekip, da slučajno ne bi bili z napačno ponujenimi stavami ob zaslužek. Na voljo so jim rezultati zadnjih medsebojnih prijateljskih tekem. Predikat win(ekipa1, ekipa2, rezultat) pove, da je prva ekipa premagala drugo z določenim rezultatom.
| win(portugal, saudi_arabia, 3-0). | win(mexico, paraguay, 2-1). |
| win(mexico, congo, 2-1). | win(argentina, portugal, 3-2). |
| win(mexico, gana, 1-0). | win(portugal, croatia, 2-0). |
| win(netherlands, ivory_coast, 3-1). | win(argentina, hungary, 2-1). |
| win(netherlands, ecuador, 1-0). | win(portugal, egypt, 2-0). |
| win(croatia, argentina, 3-2). | win(ivory_coast, slovenia, 3-0). |
| win(south_corea, mexico, 1-0). | win(netherlands, mexico, 2-1). |
Podvprašanje 1
Poleg posameznih rezultatov je za pobiralce stav zanimiva tudi gol razlika posameznih moštev; to je razlika vseh danih in dobljenih golov na prijatelskih tekmah.
Napišite predikat gd(Team, GD), ki za podano moštvo vrne njegovo gol razliko.(35%)
Rešitev
gd(Team,GD) :- findall(X,(win(Team,_,X)),D), sum(D,Dobljeni), findall(X,(win(_,Team,X)),Z), sum(Z,Zgubljeni), GD is Dobljeni-Zgubljeni. sum([],0). sum([H|T],GD) :- sum(T,G2), GD is G2+H.
Preseljena Rešitev
gd(Team, GD):- %Dobljene tekme findall(X, win(Team, _, X-Y), XL), findall(Y, win(Team, _, X-Y), YL), sumListValues(XL, XS), sumListValues(YL, YS), DobljeniGoli is (XS - YS), %Zgubljene tekme findall(LX, win(_, Team, LX-LY), LXL), findall(LY, win(_, Team, LX-LY), LYL), sumListValues(LXL, LXS), sumListValues(LYL, LYS), ZgubljeniGoli is (LXS - LYS), GD is DobljeniGoli - ZgubljeniGoli. sumListValues([], 0). sumListValues([X|Y], Sum):- sumListValues(Y, Sum1), Sum is Sum1 + X.
Verjetno obstaja bolj elegantna rešitev. Če jo kdo ima naj me prosim popravi.
Elegantnejša rešitev
gd(Team,GD):-findall(X,(win(Team,_,X-Y);win(_,Team,Y-X)),Dani), findall(Y,(win(Team,_,X-Y);win(_,Team,Y-X)),Prejeti), countGoals(Dani,N1), countGoals(Prejeti,N2), GD is N1-N2. countGoals([],0). countGoals([G|R],N):-countGoals(R,N1),N is N1+G.
Popravljena elegantnejša rešitev.
Še ena - s sum:
gd(Team,GD):- findall(X,(win(Team,_,X-Y);win(_,Team,Y-X)),Dani), findall(Y,(win(Team,_,X-Y);win(_,Team,Y-X)),Prejeti), sum(Dani,N1), sum(Prejeti,N2), GD is N1-N2.
Še najelegantnejša rešitev:):
gd(Team,Gd):- findall(G,((win(Team,_,X-Y);win(_,Team,Y-X)),G is X-Y),L), sumlist(L,Gd).
Podvprašanje 2
Kaj odgovori prolog na naslednja vprašanja? V pravilnem vrstnem redu navedite vse odgovore! (20%)
a) ?- win(portugal, X, 2-0).
b) ?- win(netherlands, X, _).
c) ?- win(X, mexico, _), !, win(mexico, Y, _).
d) ?- win(X, Y, _-2).
Rešitev
a)
X = croatia;
X = egypt;
No
b)
X = ivory_coast
X = ecuador
X = mexico
c)
- X = south_corea,
- Y = paraguay;
- X = south_corea,
- Y = congo
- X = south_corea,
- Y = gana
d)
- X = argentina,
- Y = portugal;
- X = croatia,
- Y = argentina;
Podvprašanje 3
Kako bi zastavili naslednja vprašanja?(20%) Pozor!! NE PISATI PROGRAMCKOV AMPAK IZJAVE!
a)Katere ekipe je premagala argentina?
b)Ali obstaja kakšen cikel treh ekip, tako da je prva ekipa premagala drugo, druga je premagala tretjo in tretja je premagala prvo?
c)S koliko različnimi ekipami je prijateljske tekme igrala argentina?
d)Katere ekipe so katerokoli drugo ekipo premagale za vsaj dva gola (zanima nas seznam takšnih ekip brez ponavljanja)?
Resitev
a) win(argentina, X,_).
b) win(Y,X,_), win(X,Z,_), win(Z,Y,_).
c)
findall(X,((win(argentina,X,_));(win(X,argentina,_))),L).
Mislim da zgornja rešitev ni pravilna, saj bo iste ekipe 2x štela. Prav tako, je treba podati število različnih ekip in jih ne našteti.
Moja rešitev
setof(Z,Z^D^F^(win(argentina,Z,D);win(Z,argentina,F)),_L), count(_L, X).
Ampak namesto count na koncu verjetno uporabiš length()? Moja rešitev
findall(N,(win(argentina,N,_);win(N,argentina,_)),_Stevilo), length(_Stevilo,M).
Tretja rešitev
findall(X,(win(argentina,X,_);win(X,argentina,_)),_Seznam), setof(X,memeber(X,_Seznam),_Seznam1), length(_Seznam1,N).
d)
setof(X, (R^(win(X,_,R)), R>=2), S).
Rešitev ni prava! To je prava rešitev:
findall(X,(win(X,_,Y-Z), N is Y-Z, N>=2),_Seznam), setof(X,member(X,_Seznam),Seznam1).
Namesto N is Y-Z, N>=2, lahko napišemo 2>=Y-Z
Podvprašanje 4
Ekipe bodo v prvem krogu tekmovanja razdeljene po skupinah. Predikat group(Team, Group) pove v kateri skupini igtra katera ekipa. Za ekipo velja, da je varna (glede uvrstitve v naslednji krog), če jo v prijateljskih tekmah ni premagala kakšna ekipa iz iste skupine. Nespretni pobiralec stav je za to, da bi izvedel katere ekipe so varne napisal naslednji program:(25%)
safe(Team):-
group(Team, G), group(Opponent, G), \+win(Opponent, Team, _).
a) Pomagajte nerodnemu pobiralcu stav in program ustrezno popravite!
b) Dodajte pogoj, da je ekipa za katero preverjate, če je varna, odigrala vsaj dve tekmi z nasprotnicami iz iste skupine(lahko tudi dve tekmi z istim nasprotnikom).
Resitev
a)
safe(Team):- (group(Team, G), group(Opponent, G), win(Opponent, Team, _)) -> fail ; true.
b)
safe1(Team):- findall(Opponent, (group(Team, G), group(Opponent, G), win(Team, Opponent, _)), Z), length(Z, K), 2 =< K, safe(Team).