99. Prolog feladat GY (gyakorló) feladat --------------------- Tekintse az alábbi Prolog programot és döntse el mindegyik célról, hogy hogyan fut le: - sikerül, - meghiúsul, vagy - hibát jelez! Sikeres futás esetén adja meg az összes olyan változó értékét, amelynek neve nem aláhúzás-jellel (_) kezdődik. Ha egy cél többféleképpen is sikerülhet, akkor adja meg az összes lehetséges behelyettesítést pontosvesszőkkel elválasztva! Mindegyik célt a Prolog interpreternek önmagában adjuk oda, azaz futásának kezdetén a célban előforduló változóknak nincs értéke. Feltételezzük, hogy a `lists' könyvtár be van töltve. p(1). p(2). p(X) :- X > 1. m(2, 0). m(1, 1). m(1, 3). m(2, 1). m(_, 4). q(X) :- m(_, X), p(X). (a) ?- select(1, [2,X,3], L). (b) ?- number_codes(123, [_|L]), number_codes(X, L). (c) ?- \+ \+ X = 1, X = 2. (d) ?- m(1, X). (e) ?- q(X). Az (a)-(d) alfeladatok értéke 1-1 pont, az (e) alfeladaté 3 pont E (elméleti) feladat -------------------- Adjon nagyvonalú áttekintést az alábbi anyagrészről, kb 3-5 percben. Ha a téma konkrét Prolog eljárásokról szól, akkor a felkészülés részeként célszerű ezen eljárások közül legalább egynek a kódját felírnia. A nyelv végrehajtási mechanizmusa (redukciós lépés, visszalépés) Az elméleti feladatra 7 pont kapható. P1 (programozási) minta-feladat ------------------------------- Segédeljárás: Egy számlistában vízesésnek hívunk egy olyan legalább kételemű, folyamatos részlistát, amely szigorúan monoton csökkenő, a szomszédos elemek különbsége legalább 3, és egyik irányba sem terjeszthető ki ezen tulajdonságok megtartásával. Írjon egy olyan Prolog eljárást, amely eldönti, hogy egy egészekből álló lista elején egy vízesés áll-e, és visszadja a vízesés első és utolsó elemét, valamint a bemeneti listának a megtalált vízesés utáni részét! Ha a bemeneti lista nem vízeséssel kezdődik, az eljárás hiúsuljon meg! % kezdo_vizeses(L, K, V, M): az L egészlista elején egy vízesés áll, amelynek % első eleme K, utolsó eleme V, az utána következő elemek listája M. % :- pred kezdo_vizeses(list(int)::in, int::out, int::out, list(int)::out). Példa: | ?- kezdo_vizeses([], K, V, M). no | ?- kezdo_vizeses([1,2,-5,20,15,12,7,3,0,-2], K, V, M). no | ?- kezdo_vizeses([2,-5,20,15,12,7,3,0,-2], K, V, M). K = 2, V = -5, M = [20, 15, 12, 7, 3, 0, -2] ? ; no Teljes feladat: A kezdo_vizeses/3 predikátum segítségével írjon egy olyan Prolog eljárást, amely felsorolja egészek egy adott listájában az összes benne megtalálható vízesés első és utolső elemét! A vízeséseket előfordulási sorrendjükben vegye sorra! % vizeses(L, K, V): K és V egy az L egészlistában előforduló vízesés első % illetve utolsó eleme. % :- pred vizeses(list(int)::in, int::out, int::out). Példa: | ?- vizeses([0,2,5,5], K, V). no | ?- vizeses([1,2,-5,20,15,12,7,3,0,-2], K, V). K = 2, V = -5 ; K = 20, V = 0 ; no A segédeljárásra 11 pont, a teljes feladatra 21 pont kapható. P2 (programozási) minta-feladat ------------------------------- Segédeljárás: Egy Prolog kifejezés szimmetrikus, ha a szimmetrikus pozíciójú argumentumai azonosak (azaz egy n-argumentumú kifejezés szimmetrikus, ha 1. és n., 2. és (n-1).,..., i. és (n+1-i). argumentuma azonos). Az argumentum nélküli kifejezéseket szimmetrikusaknak tekintjük. Írjon Prologban egy olyan eljárást, amely egy tetszőleges Prolog kifejezésről megállapítja, hogy az szimmetrikus-e! Az azonosság eldöntésére az ==/2 beépített eljárást használhatja. Vigyázat, a kifejezés lehet változó! % szimmetrikus(Kif): igaz, ha Kif szimmetrikus. % :- pred szimmetrikus(univ::in). Példák: | ?- szimmetrikus(f(g(X),h(a,a),j(3,4,3))). ----> no | ?- szimmetrikus(f(g(a,a),h(2),g(a,a))). ----> yes | ?- szimmetrikus(f(1)). ----> yes | ?- szimmetrikus(1-X). ----> no | ?- szimmetrikus(X-X). ----> yes | ?- szimmetrikus(X). ----> yes Teljes feladat: A szimmetrikus/1 predikátum segítségével írjon egy olyan Prolog eljárást, amely egy tetszőleges Prolog kifejezés összes szimmetrikus részstruktúráját felsorolja. A részkifejezések előfordulási sorrendjét őrizze meg! Vigyázat, a kifejezés lehet változó és benne is előfordulhatnak változók! % szimmetrikus_resze(Kif, Resz): Resz a Kif-nek szimmetrikus részstruktúrája, % :- pred szimmetrikus_resze(univ::in, univ::out). Példák: | ?- szimmetrikus_resze(f(1,a,1), R). R = f(1,a,1) ? ; R = 1 ? ; R = a ? ; R = 1 ? ; no | ?- szimmetrikus_resze(f(2+1+1,3+3+3), R). R = 2 ? ; R = 1 ? ; R = 1 ? ; R = 3+3 ? ; R = 3 ? ; R = 3 ? ; R = 3 ? ; no | ?- szimmetrikus_resze(g(X,Y), R). R = X ? ; R = Y ? ; no A segédeljárásra 11 pont, a teljes feladatra 21 pont kapható. P3 (programozási) minta-feladat ------------------------------- Egy A atom egy N nemnegatív egésszel vett szorzatán az A atom N-szeri egymás után fűzésével kapott atomot értjük. Segédeljárás: Írjon Prolog nyelven egy eljárást amelynek bemenete egy N nemnegatív egész és egy A atom, kimenete pedig N és A szorzata! % szorzata(N, A, NA): NA az N nemnegatív egész és az A atom szorzata. % :- pred szorzata(int::in, atom::in, atom::out). Példák: | ?- szorzata(2, korte, NA). ----> NA = kortekorte ? ; no | ?- szorzata(0, korte, NA). ----> NA = '' ? ; no Teljes feladat: A szorzata/3 eljárás segítségével, könyvtári eljárások használata nélkül készítsen el egy Prolog eljárást, amely egy számokból és atomokból a + és * operátorokkal felépített a-kifejezés értékét kiszámítja! Ha A atomot, N nemnegatív egészet jelöl, akkor az AKif-fel jelölt a-kifejezéseket a következő nyelvtani szabállyal jellemezhetjük: AKif ---> A | N*AKif | AKif*N | AKif+AKif. A + operátor a konkatenálást jelöli, a * operátor pedig a segédfeladatban definiált szorzást. % erteke(OpKif, Ertek): Az OpKif operátoros ábrázolású % fent definiált alakú kifejezés értéke Ertek. % :- pred erteke(univ::in, atom::out). Példák: | ?- erteke(alma, E). E = alma ? ; no | ?- erteke(ba*2, E). E = baba ? ; no | ?- erteke(2*ba, E). E = baba ? ; no | ?- erteke(alma+'_korte'+2*'_barack', E). E = alma_korte_barack_barack ? ; no A segédeljárásra 11 pont, a teljes feladatra 21 pont kapható.