Néhány prolog feladat megoldása

Az egyetemen ( PTE TTK Programtervező informatikus ) többek között prolog kurzust is felvettem. Inkább csak érdekességként, így nem merültem el mélyebben a témában, de néhány gyakorló feladatot megosztanék a nagyközönséggel is. Hosszú magyarázatot nem mellékelek, mivel már régen tanultam, és talán nem is tudnék részletesen magyarázni. Azért a fent linkelt wikipédián kívül még egy hasznos oldal: Link

Egy lista elemeinek száma

  1. %---------------------- Egy lista elemeinek száma ---------------------------------
  2.  
  3. %üres lista hossza 0
  4. length1([],0).
  5. %egy lista hossza, ami több mint egy elemet tartalmaz,
  6. %és mindegy mi az első eleme,
  7. length1([_|Y],Z):-
  8.         %pont olyan hosszú, mint az első elemét leszámítva a többi elemének száma,
  9.         length1(Y,V),
  10.         %plusz az első elem
  11.         Z is V+1.

Lista hosszának fele

  1. %----------------------   Lista hosszának fele -------------------------------------
  2.  
  3. %egy lista hosszának fele
  4. length2([X|Y],U):-
  5.         %a lista teljes hossza
  6.         length1([X|Y],Z),
  7.         %és a teljes hossz egyszerűen osztva kettővel
  8.         U is Z / 2.

Modulo számítás

  1. %---------------------   Modulo számítás -------------------------------------------
  2.  
  3. %A mod B pontosan A
  4. modulo(A,B,A):-
  5.         %ha A már eleve kisebb, mint B
  6.         A<B,
  7.         %és ekkor már biztos hogy nem kell a többi illeszkedést vizsgálni. Kiléphetünk a ! jellel.
  8.         !.
  9. modulo(A,B,X):-
  10.         C is A-B, modulo(C,B,X).

Minden egymást követő két elem felcserélése egymással

  1. %------------------------ Minden egymást követő két elem felcserélése egymással ------
  2.  
  3. %üres lista elemeinek cseréje ugyanúgy üres listát ad
  4. pcsere([],[]).
  5. %egy egy elemű lista elemeinek felcserélése ugyanazt az egy elemet adja
  6. pcsere([X],[X]):-
  7.         %és ha csak egy elem maradt, akkor kilépünk a keresésből
  8.         %mert másképp felajánlaná hogy keres tovább a következő szabály szerint
  9.         !.
  10. %Egy legalább 2 elemű lista elemeinek cseréje
  11. pcsere([X,Y|Z],[X2,Y2|Z2]):-
  12.         %az első két elem felcserélése
  13.         X2 is Y, Y2 is X,
  14.         %majd a maradék elem cseréje rekurzív hívással    
  15.         pcsere(Z,Z2).

Egy lista első eleme

  1. %----------------------- Egy lista első eleme ----------------------------------------
  2.  
  3. %üres lista első eleme egy üres lista
  4. eleje([],[]).
  5. %egy legalább egy elemű lista első eleme az első elem, és a vége mindegy mi
  6. eleje([X|_],X).

Egy lista utolsó eleme

  1. %----------------------- Egy lista utolsó eleme --------------------------------------
  2.  
  3. %egy üres lista utolsó eleme egy üres lista
  4. vege([],[]).
  5. %Egy egy elemű lista utolsó eleme az egyetlen eleme
  6. vege([Y],Y).
  7. %egy több mint egy elemű lista utolsó eleme
  8. vege([_|Y],Z):-
  9.         %a lista farkának utolsó eleme rekurzívan keresve
  10.         vege(Y,Z),
  11.         % majd pedig megszakítjuk a keresést, mert visszaugrana az első szabályra
  12.         !.

Egy lista első és utolsó eleme

  1. %---------------- Egy lista első és utolsó eleme ------------------------------------
  2.  
  3. %üres lista esetén mindkettő üres lista
  4. elejevege([],[],[]).
  5. %egy nem üres lista első és utolsó eleme
  6. elejevege([X|Y],V,Z):-
  7.         %az első eleme
  8.         eleje([X|Y],V),
  9.         %és az utolsó eleme
  10.         vege([X|Y],Z),
  11.         %és ha megvan, ki kell lépni, hogy ne ugorjon vissza az első szabályra      
  12.         !.

Lista jobb oldalára fűzés

  1. %----------------------- lista összefűzés -----------------------------
  2. %----------------------- Jobb oldalra fűzés ---------------------------
  3. %------------- Ez az órai "append" másolata ---------------------------
  4.  
  5. %üres listához bármit fűzünk, az önmaga lesz
  6. rappend([],L,L).
  7. %ha egy nem üres listához fűzünk hozzá elemet
  8. rappend([X|L1],L2,[X|L3]):-
  9.         %az az első lista farka, és a második lista összefűzött változata lesz
  10.         rappend(L1,L2,L3).

Lista bal oldalára fűzés

  1. %------------------------ bal oldalra fűzés ---------------------------
  2. %------------ Ez már ismét saját, az rappend-et felhasználva ----------
  3.  
  4. %üres listához balról is bármit fűzünk, az önmaga
  5. lappend([],L,L).
  6. %Bármi más listához hozzáfűzni balról annyi,
  7. lappend(L1,L2,L3):-
  8.         %mint a második listához jobbról fűzni az elsőt
  9.         rappend(L2,L1,L3).

Lista dekrementálása

  1. %----------------------- Lista dekrementálása  -------------------------
  2.  
  3. %üres lista dekrementáltja üres lista
  4. decrList([],[]).
  5. %Egy lista dekrementáltja
  6. decrList(X,Y):-
  7.         %ha az valójában csak egy szám
  8.         number(X),
  9.         %akkor a szám minusz 1
  10.         Y is X-1,
  11.         %és akkor a lista végén vagyunk, nem kell a következő szabály
  12.         !.
  13. %az egy elemű lista dekrementáltja
  14. decrList([X],[Y]):-
  15.         %ha az egyetlen eleme egy szám
  16.         number(X),
  17.         %akkor a szám, minusz 1 elemet tartalmazó egy elemű lista   
  18.         Y is X-1,
  19.         %És mivel ekkor is a lista végén vagyunk, itt sem kell már a következő szabály  
  20.         !.
  21. %több elemű lista dekrementálja
  22. decrList([X|Y],[X1|Y1]):-
  23.         %az első elem dekrementáltja
  24.         decrList(X,X1),
  25.         %és az összes többi elem dekrementáltja    
  26.         decrList(Y,Y1),
  27.         %ha megvan, akkor nem kérjük újra az első szabályt
  28.         !.

Többszintű listák összege

  1. %------------------- órai tovább fejlesztése töbszintű listák összegére -------
  2. %üres lista hossza 0
  3. sumList([],0).
  4. %egy lista összege, önmaga
  5. sumList(X,X):-
  6.         %ha az a lista valójában egy szám
  7.         number(X).
  8. %egy nem üres, hosszabb lista összege
  9. sumList([X|Y],Z):-
  10.         %az első elemének összege,
  11.         sumList(X,S1),
  12.         %és a lista farkának összege
  13.         sumList(Y,S2),
  14.         Z is S1+S2,
  15.         %Ha megvan az összeg, nem kérjük az első szabályt újra
  16.         !.

Numerikus lista.

  1. %------------------ Numerikus lista. ( Mert az órai nem működött ) ---------
  2.  
  3.  
  4. %üres lista legyen numerikus lista
  5. isNumericList([]).
  6. %egy elemű lista akkor numerikus,
  7. isNumericList([X]):-
  8.         %ha az egyetlen eleme szám    
  9.         number(X),
  10.         %és ha már csak egy elemű lista van, akkor nem kell a többi szabály       
  11.         !.
  12. %egy több elemű lista akkor numerikus
  13. isNumericList([X|Y]):-
  14.         %ha az első eleme szám
  15.         number(X),
  16.         %és a lista farka numerikus lista
  17.         isNumericList(Y).

Lista végigjárása

  1. %a lista első elemét vesszük először
  2. next1([X|_],X).
  3. %utána a lista farkának
  4. next1([_|X],NEXT):-
  5.         %következő elemét vesszük
  6.         next1(X,NEXT).

Második paraméter az első paramétert leszámítva megegyezik-e a többivel.
tail([_|L],L).
Az első paraméter benne van-e a listában:

  1. %Ha a lista (2. paraméter) első eleme a keresett elem, akkor kész
  2. member(X,[X|_]).
  3. %Ha nem az első elem, akkor keressük a lista "farkában".
  4. member(X,[_|L]):-member(X,L).

Lista megfordítása egy lista hozzáfűzésével.

  1. %Üres listához hozzáfűzve egy listát önmagát kapjuk
  2. revapp([],L,L).
  3. %Legyen X az első elem, L1 az összes többi. L2 a hozzáfűzendő lista és L3 a megfordított lista.
  4. revapp([X|L1],L2,L3):-
  5. %Önmagát híja rekurzívan, amíg nem tud újra az első szabályra illeszkedni. Ahol L1 üres lista.
  6. %L1 mindig az első paraméter "farka", tehát előbb utóbb üres lesz. A hozzáfűzendő lista pedig
  7. %mindig az aktuális lista első eleme és a végén az előzőleg hozzáfűzött lista.
  8. revapp(L1,[X|L2],L3).

Lista megfordítása

  1. %L a lista, REV a fordítottja.
  2. reverse(L,REV):-
  3. %Fűzzük hozzá a listához az üres listát revapp-al. (előző szabály)
  4. revapp(L,[],REV).

A fent leírtak gyakorlatilag szabályok. Amire illeszkedést lehet vizsgálni. Aminek eredménye logikai érték. Ha pedig érték helyett változót adunk meg egy paraméter helyett, akkor megpróbálja az összes lehetséges illeszkedést megkeresni a változóra és feltölti az értékekkel.

A szabályok helyességéért nem tenném tűzbe a kezem, de annak idején tesztelve látszólag jól működtek. Aki a prolog után érdeklődik, a következő oldalról letöltheti az SWI-prolog programot akár windowsra, akár linuxra, de még MacOS-re is: LINK

Kategóriák: 
Megosztás/Mentés

Hozzászólások

Anonymous képe

Szia most kezdtem tanulnia prologot és szeretnék érdeklődni hogy egy ilyen jellegű feladatot hogy lehetne megvalósítani prologban.

Írjuk meg jobb-rekurziós módon a faktoriálist, és nézzük meg nyomkövetéssel!
2. Faktoriális még másképp -
egy sima rekurziós és egy listás megvalósítása.

A segítséget előre is köszönöm szépen.

Rimelek képe

Szia. Én nagyon régen nem prologoztam és akkor sem voltam profi. Most nem is érek rá. Majd este ránézek a kérdésedre újra.

De mennyit is tudsz a prologról és melyik részénél akadsz el? Vagy eleve ott, hogy jobb rekurzió hogy oldható meg prologban?

Új hozzászólás