Programozási paradigmák, nagyzárthelyi, 2000. március 27. 17.15--18.45
                   Munkaidő: 90 perc, összpontszám: 60

                     Prolog, ,,A'' csoport (30 pont)


A Prolog eljárás megírását kérő feladatokban a jegyzetben szereplő összes
Prolog eljárás (akár beépített, akár a jegyzetben definiált) szabadon
használható.  Ha segédeljárást definiál, feltétlenül adjon meg hozzá
fejkommentet; enélkül a megoldás nem értékelhető, vagy csak csökkentett
pontszámot kaphat.  Törekedjék egyszerű, tömör és hatékony programozásra;
használjon jobbrekurziót, kerülje a felesleges hívásokat (pl. az append
eljárás felesleges használatát)!


1. Írja fel az alábbi kifejezések alapstruktúra-alakját (azaz szintaktikus
   édesítőszerek nélküli formáját) vagy rajzolja fel a hozzájuk tartozó
   fastruktúrákat! Állapítsa meg, hogy a két kifejezés egyesíthető-e, és ha
   igen, milyen behelyettesítéssel!                                           (3 pont)

   .(A*B+C, [1*C])                       [X+2,X]


   Megoldás:

   .(+(*(A,B),C), .(*(1,C), []))         .(+(X,2),.(X,[]))

   Egyesítés: A = 1, B = C = 2, X = 1*2

2. Egy célsorozat keresési fája egy olyan irányított gráf, amelynek
   csúcsaiban célsorozatok vannak és két csúcs között akkor megy él, ha a
   kiinduló csúcs célsorozatából egyetlen (Prolog) redukciós lépéssel
   eljuthatunk a cél csúcs célsorozatába.  Az élek a redukció során
   alkalmazott klóz sorszámával vannak címkézve.  A fa gyökerében a teljes
   kiindulási célsorozat van, az üres célsorozatot egy négyzettel jelöljük.

   Rajzolja fel az alábbi célsorozat keresési fáját!  A fa nem üres
   célsorozatot tartalmazó leveleinél jelezze a visszalépést!  (A select
   és a write szavakat rövidítheti (s ill. w).)                               (7 pont)

   | ?- select(1, A, [2,3]), write(A).

   A select/3 eljárás definíciója:

   (1) select(E, [E|L], L).
   (2) select(E, [X|T], [X|L]) :-
             select(E, T, L).


   Megoldás:
Az A2 feladat megoldása
3. Írjon olyan Prolog eljárást, amely előállítja egy lista első N elemének
   elhagyásával keletkező listát!                                             (7 pont)

   % dob(N, L, M): M az L lista első N elemének elhagyásával áll elő.
   % N és L adott, bemenő paraméter, M kimenő paraméter.

   | ?- dob(2, [1,2,3], L).              L = [3] ? ; no
   | ?- dob(-1, [1,2,3], L).             no
   | ?- dob(8, [1,2,3], L).              no


   Megoldás:

   dob(0, L0, L) :- !, L = L0.
   dob(N, [_|T], M) :-
	   N > 0,
	   N1 is N-1,
	   dob(N1, T, M).


4. Írjon olyan Prolog eljárást, amely egészek egy listáját előjelesen
   rendezi!  Egy lista előjelesen rendezett, ha a benne előforduló negatív
   elemek megelőzik a nem negatív elemeket.  A rendezés legyen konzervatív,
   azaz két elem sorrendjét ne változtassa meg, ha azonos az előjelük!        (13 pont)

   % jelrend(L, R): Az L lista konzervatív előjeles rendezettje R.
   % L adott, bemenő paraméter, R kimenő paraméter.

   | ?- jelrend([1,2,-3,5,-4], R).       R = [-3,-4,1,2,5] ? ; no

   Első megoldás:

   jelrend(L, R) :-
   	   jelrend(L, N, NN),
   	   append(N, NN, R).
   
   % jelrend(L, N, NN): Az L lista negatív elemeinek listája N, nemnegatív
   % elemeinek listája NN.
   %
   % Ha valaki nem érti mit csinál a vágó, az kiszedheti, de akkor a
   % harmadik klózban kikommentezett részt vissza kell rakni.  Ilyenkor
   % az N = [E|N1] egyesitest a klóz fejébe lehet írni.
   jelrend([], [], []).
   jelrend([E|L], N, NN) :-
   	   E < 0, !,
   	   N = [E|N1],
   	   jelrend(L, N1, NN).
   jelrend([E|L], N, [E|NN]) :-
   	   /* E >= 0, */
   	   jelrend(L, N, NN).


   Második megoldás:

   % Ez a megoldás kicsit hatékonyabb, mert elkerüli az append meghívását.
   % Mindezt azon az áron, hogy a segédeljárás gyűjtőargumentum-párokkal dolgozik.
   jelrend1(L, R) :-
   	   jelrend1(L, R, X, X, []).
   
   % jelrend1(I, L, LT, R, RT): I lista negatív elemeinek listája L-LT,
   % a nem negatív  elemeinek listája R-RT.
   jelrend1([], L, L, R, R).
   jelrend1([H|T], L, LT, R, RT) :-
   	   H < 0, !,
   	   L = [H|L1],
   	   jelrend1(T, L1, LT, R, RT).
   jelrend1([H|T], L, LT, [H|R1], RT) :-
   	   /* H >= 0, */
   	   jelrend1(T, L, LT, R1, RT).
   



   Programozási paradigmák, nagyzárthelyi, 2000. március 27. 17.15--18.45
                   Munkaidő: 90 perc, összpontszám: 60

                     Prolog, ,,B'' csoport (30 pont)


A Prolog eljárás megírását kérő feladatokban a jegyzetben szereplő összes
Prolog eljárás (akár beépített, akár a jegyzetben definiált) szabadon
használható.  Ha segédeljárást definiál, feltétlenül adjon meg hozzá
fejkommentet; enélkül a megoldás nem értékelhető, vagy csak csökkentett
pontszámot kaphat.  Törekedjék egyszerű, tömör és hatékony programozásra;
használjon jobbrekurziót, kerülje a felesleges hívásokat (pl. az append
eljárás felesleges használatát)!


1. Írja fel az alábbi kifejezések alapstruktúra-alakját (azaz szintaktikus
   édesítőszerek nélküli formáját) vagy rajzolja fel a hozzájuk tartozó
   fastruktúrákat! Állapítsa meg, hogy a két kifejezés egyesíthető-e, és ha
   igen, milyen behelyettesítéssel!                                           (3 pont)

   [5+3+A,B+C]                         [X+y|.(X,Z)]

   Megoldás:

   .(+(+(5,3),A), .(+(B,C), []))       .(+(X,y), .(X,Z))

   Egyesítés: A = y, B = 5, C = 3, X = 5+3, Z = []

2. Egy célsorozat keresési fája egy olyan irányított gráf, amelynek
   csúcsaiban célsorozatok vannak és két csúcs között akkor megy él, ha a
   kiinduló csúcs célsorozatából egyetlen (Prolog) redukciós lépéssel
   eljuthatunk a cél csúcs célsorozatába.  Az élek a redukció során
   alkalmazott klóz sorszámával vannak címkézve.  A fa gyökerében a teljes
   kiindulási célsorozat van, az üres célsorozatot egy négyzettel jelöljük.

   Rajzolja fel az alábbi célsorozat keresési fáját!  A fa nem üres
   célsorozatot tartalmazó leveleinél jelezze a visszalépést!  (A select
   és a write szavakat rövidítheti (s ill. w).)                               (7 pont)

   | ?- select(1, [1,2,1], A), write(A).

   A select/3 eljárás definíciója:

   (1) select(E, [E|L], L).
   (2) select(E, [X|T], [X|L]) :-
             select(E, T, L).

   Megoldás:
A B2 feladat megoldása
3. Írjon olyan Prolog eljárást, amely előállítja egy lista első N eleméből
   álló listát!                                                               (7 pont)

   % vesz(N, L, M): M az L lista első N elemének a listája.
   % N és L adott, bemenő paraméter, M kimenő paraméter.

   | ?- vesz(2, [1,2,3], L).             L = [1,2] ? ; no
   | ?- vesz(-1, [1,2,3], L).            no
   | ?- vesz(8, [1,2,3], L).             no

   Megolás:

   vesz(0, _, L) :- !, L = [].
   vesz(N, [H|T], [H|L]) :-
   	   N > 0,
   	   N1 is N-1,
   	   vesz(N1, T, L).


4. Írjon olyan Prolog eljárást, amely egy listát átrendez úgy, hogy az
   eredeti listában páratlan indexű elemeket előrehozza, de az azonos
   paritású indexszel rendelkezők sorrendjét nem változtatja meg!  (A listát
   1-től kezdve indexeljük.)
   Pontosabban: az N hosszú A lista páros permutáltja az N hosszú B
   lista, ha B első (N+1)//2 eleme az A páratlan indexű elemeivel azonos
   (a sorrend megtartásával), és B fennmaradó N//2 eleme pedig A páros
   indexű elemeivel egyezik meg (szintén a sorrend megtartásával). Itt a 
   // művelet egész-osztást jelöl.                                            (13 pont) 

   % parperm(L, P): P lista az L lista páros permutáltja.
   % L adott, bemenő paraméter, P kimenő paraméter.

   | ?- parperm([a,b,c,d,e], P).         P = [a,c,e,b,d] ? ; no
   | ?- parperm([a,b,c,d,e,f], P).       P = [a,c,e,b,d,f] ? ; no

   Első megoldás:

   parperm(L, R) :-
   	   parperm(L, Pt, Ps),
   	   append(Pt, Ps, R).
   
   % parperm(I, L, R): I lista páratlan indexű elemeinek listája L,
   % páros indexű elemeinek listája R.
   parperm([], [], []).
   parperm([E|L], [E|Pt], Ps) :-
   	   parperm(L, Ps, Pt).


   Második megoldás:

   % Ez a megoldás kicsit hatékonyabb, mert elkerüli az append meghívását.
   % Mindezt azon az áron, hogy a segédeljárás gyűjtőargumentum-párokkal dolgozik.
   parperm1(L, R) :-
   	   parperm1(L, R, X, X, []).
   
   % parperm1(I, L, LT, R, RT): I lista páratlan indexű elemeinek listája L-LT,
   % páros indexű elemeinek listája R-RT.
   parperm1([], L, L, R, R).
   parperm1([H|T], [H|L], LT, R, RT) :-
   	   parperm1(T, R, RT, L, LT).