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

%---------------------- Egy lista elemeinek száma ---------------------------------

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

Lista hosszának fele

%----------------------   Lista hosszának fele -------------------------------------

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

Modulo számítás

%---------------------   Modulo számítás -------------------------------------------

%A mod B pontosan A
modulo(A,B,A):-
        %ha A már eleve kisebb, mint B
        A<B,
        %és ekkor már biztos hogy nem kell a többi illeszkedést vizsgálni. Kiléphetünk a ! jellel.
        !.
modulo(A,B,X):-
        C is A-B, modulo(C,B,X).

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

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

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

Egy lista első eleme

%----------------------- Egy lista első eleme ----------------------------------------

%üres lista első eleme egy üres lista
eleje([],[]).
%egy legalább egy elemű lista első eleme az első elem, és a vége mindegy mi
eleje([X|_],X).

Egy lista utolsó eleme

%----------------------- Egy lista utolsó eleme --------------------------------------

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

Egy lista első és utolsó eleme

%---------------- Egy lista első és utolsó eleme ------------------------------------

%üres lista esetén mindkettő üres lista
elejevege([],[],[]).
%egy nem üres lista első és utolsó eleme
elejevege([X|Y],V,Z):-
        %az első eleme
        eleje([X|Y],V),
        %és az utolsó eleme
        vege([X|Y],Z),
        %és ha megvan, ki kell lépni, hogy ne ugorjon vissza az első szabályra      
        !.

Lista jobb oldalára fűzés

%----------------------- lista összefűzés -----------------------------
%----------------------- Jobb oldalra fűzés ---------------------------
%------------- Ez az órai "append" másolata ---------------------------

%üres listához bármit fűzünk, az önmaga lesz
rappend([],L,L).
%ha egy nem üres listához fűzünk hozzá elemet
rappend([X|L1],L2,[X|L3]):-
        %az az első lista farka, és a második lista összefűzött változata lesz
        rappend(L1,L2,L3).

Lista bal oldalára fűzés

%------------------------ bal oldalra fűzés ---------------------------
%------------ Ez már ismét saját, az rappend-et felhasználva ----------

%üres listához balról is bármit fűzünk, az önmaga
lappend([],L,L).
%Bármi más listához hozzáfűzni balról annyi,
lappend(L1,L2,L3):-
        %mint a második listához jobbról fűzni az elsőt
        rappend(L2,L1,L3).

Lista dekrementálása

%----------------------- Lista dekrementálása  -------------------------

%üres lista dekrementáltja üres lista
decrList([],[]).
%Egy lista dekrementáltja
decrList(X,Y):-
        %ha az valójában csak egy szám
        number(X),
        %akkor a szám minusz 1
        Y is X-1,
        %és akkor a lista végén vagyunk, nem kell a következő szabály
        !.
%az egy elemű lista dekrementáltja
decrList([X],[Y]):-
        %ha az egyetlen eleme egy szám
        number(X),
        %akkor a szám, minusz 1 elemet tartalmazó egy elemű lista   
        Y is X-1,
        %És mivel ekkor is a lista végén vagyunk, itt sem kell már a következő szabály  
        !.
%több elemű lista dekrementálja
decrList([X|Y],[X1|Y1]):-
        %az első elem dekrementáltja
        decrList(X,X1),
        %és az összes többi elem dekrementáltja    
        decrList(Y,Y1),
        %ha megvan, akkor nem kérjük újra az első szabályt
        !.

Többszintű listák összege

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

Numerikus lista.

%------------------ Numerikus lista. ( Mert az órai nem működött ) ---------

%üres lista legyen numerikus lista
isNumericList([]).
%egy elemű lista akkor numerikus,
isNumericList([X]):-
        %ha az egyetlen eleme szám    
        number(X),
        %és ha már csak egy elemű lista van, akkor nem kell a többi szabály       
        !.
%egy több elemű lista akkor numerikus
isNumericList([X|Y]):-
        %ha az első eleme szám
        number(X),
        %és a lista farka numerikus lista
        isNumericList(Y).

Lista végigjárása

%a lista első elemét vesszük először
next1([X|_],X).
%utána a lista farkának
next1([_|X],NEXT):-
        %következő elemét vesszük
        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:

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

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

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

Lista megfordítása

%L a lista, REV a fordítottja.
reverse(L,REV):-
%Fűzzük hozzá a listához az üres listát revapp-al. (előző szabály)
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?