% =================================== % Deklaratív Programozás 3. gyakorlat % =================================== % I. rész: Vágó és vezérlési eljárások % ------------------------------------ :- use_module(library(lists)). % fogyo_prefix(L, P): P az L nem üres számlista lehető leghosszabb olyan prefixuma % (kezdőszelete), amely szigorúan monoton csökkenő. % GyV: Az alábbi négy változat közül elég 2-3-t elmondani, feliratni. % GyV: Ugyanez vonatkozik (arányosan) a többi többváltozatos példára % Feltételes szerkezettel. fogyo_prefix1([X|L], [X|P]) :- ( L = [Y|_], X > Y -> fogyo_prefix1(L, P) ; P = [] ). % Ugyanez vágóval. fogyo_prefix2([X,Y|L], P) :- X > Y, !, P = [X|P1], fogyo_prefix2([Y|L], P1). fogyo_prefix2([X|_], [X]). % Ugyanez "hacker" megoldással, append megoldássorendje számit fogyo_prefix3(L, P) :- append(P, R, L), last(P, X), ( R = [] ; R = [Y|_], X =< Y ), !. % Egy kicsit egyszerűbb "hacker" megoldás fogyo_prefix4(L, P) :- append(P, R, L), last(P, X), \+ (R = [Y|_], X > Y), !. % II. rész: Univ % -------------- % reszkif(Kif, R): Kif részkifejezése az R % Megjegyzés: Részkifejezésként mindig megengedjük a teljes kifejezést, % kivéve ha _valódi_ részkifejezésről beszélünk. reszkif1(Kif, Kif). reszkif1(Kif, R) :- compound(Kif), Kif =.. [_|Args], member(A, Args), reszkif1(A, R). % | ?- reszkif1(f(a,[1,3]), R). % R = f(a,[1,3]) ? ; R = a ? ; R = [1,3] ? ; R = 1 ? ; % R = [3] ? ; R = 3 ? ; R = [] ? ; no reszkif2(Kif, Kif). reszkif2(Kif, R) :- compound(Kif), functor(Kif, _, N), between(1, N, I), arg(I, Kif, A), reszkif2(A, R). % between(+N, +M, I): N =< I =< M, I egész (ahol N, M egészek). between(N, M, N) :- N =< M. between(N, M, I) :- N < M, N1 is N+1, between(N1, M, I). % int_inside(X, I): Az X kifejezés részkifejezése az I egész szám. int_inside1(X, I) :- ( integer(X) -> X = I ; compound(X), X =.. [_|Args], member(A, Args), int_inside1(A, I) ). % | ?- int_inside1(f(a,[1,3]), I). % I = 1 ? ; I = 3 ? ; no int_inside2(X, I) :- reszkif2(X, I), integer(I). % all_ints(X): Az X kifejezés összes egyszerű (nem-struktúra) % részkifejezése egész szám. all_ints1(X) :- integer(X). all_ints1(X) :- compound(X), X =..[_|Args], args_all_ints(Args). % args_all_ints(L): Az L lista minden X elemére fennáll az all_ints(X) % feltétel, azaz minden X elem minden egyszerű részkifejezése egész szám. args_all_ints([]). args_all_ints([X|L]) :- all_ints1(X), args_all_ints(L). all_ints2(X) :- integer(X). all_ints2(X) :- compound(X), X =.. [_|Args], \+ ( member(A, Args), \+ all_ints2(A) ). % forall(member(A, Args), all_ints2(A)). % GyV: A forall szerepelt az előadason! % P minden megoldására teljesül Q. forall(P, Q):- \+ ( P, \+ Q). all_ints3(X) :- forall((reszkif2(X, R),\+compound(R)), integer(R)). % Írjon Prologban egy eljárást, amely egy tetszőleges Prolog kifejezésben % minden egész számot eggyel nagyobbra cserél. Vigyázat: a kifejezésben változók % is előfordulhatnak! % % novelt(+Kif, ?Kif1): Kif1 ugyanolyan Prolog kifejezés mint Kif, csak % % minden egész szám helyett az eggyel nagyobb szám szerepel benne. % Példa: ?- novelt(f(1, X, 2, [3,4.0]), Kif1). % válasz: Kif1 = f(2, X, 3, [4,4.0]) novelt(Kif, NKif) :- integer(Kif), !, NKif is Kif+1. novelt(Kif, NKif) :- compound(Kif), !, Kif =.. [F|Args], lista_novelt(Args, NArgs), NKif =.. [F|NArgs]. novelt(Kif, Kif). lista_novelt([], []). lista_novelt([K|L], [NK|NL]) :- novelt(K, NK), lista_novelt(L, NL). % Írjon olyan Prolog eljárást, amely egy adott atomban keres egy abban % előforduló legalább kétkarakteres olyan folytonos részt, amely csupa % kisbetűből áll, és maximális, azaz egyik irányban sem terjeszthető ki % kisbetűvel! Visszalépéskor legyen hajlandó az összes ilyen részatomot % felsorolni! % % szava(Atom, Szo): Az Atom atomnak a Szo atom egy olyan folytonos része, % % amely csupa kisbetűből áll, maximális, és legalább kétbetűs. % % :- pred szava(atom::in, atom::out, int::out). % | ?- szava('a gyogy* 6ott', S). % S = gyogy; S = ott; no szava1(Atom, Szo) :- atom_codes(Atom, L), kodlista_szava(L, SzL), atom_codes(Szo, SzL). % kodlista_szava(KL, SL): a KL kódlistának az SL lista egy maximális, legalább % kételemű, csupa kisbetűből álló folytonos része. kodlista_szava([K|L], SzL) :- kisbetu(K), max_szo(L, SzL1, M), !, ( SzL = [K|SzL1] ; kodlista_szava(M, SzL) ). kodlista_szava([_|L], SzL) :- kodlista_szava(L, SzL). % K egy kisbetű kódja. kisbetu(K) :- K >= 0'a, K =< 0'z. % max_szo(L, SzL, M): Az L kódlista elején levő maximális hosszúságú, % legalább egyelemű kisbetűsorozat SzL, az L fennmaradó része M. max_szo([K|L], [K|SzL], M) :- kisbetu(K), ( max_szo(L, SzL, M) -> true ; SzL = [], M = L ). szava2(Atom, Szo) :- atom_codes(Atom, L), SzL = [_,_|_], append(L1, L2, L), append(SzL, L3, L2), forall(member(X,SzL), kisbetu(X)), \+ (last(L1, K), kisbetu(K)), \+ (L3 = [K|_], kisbetu(K)), atom_codes(Szo, SzL). % Az alábbi változat csak abban tér el az előzőtől, hogy a megtalált szó % indexpozicióját is kiadja. % Írjon olyan Prolog eljárást, amely egy adott atomban keres egy abban % előforduló legalább kétkarakteres olyan folytonos részt, amely csupa % kisbetűből áll, és maximális, azaz egyik irányban sem terjeszthető ki % kisbetűvel! Az eljárás adja ki a fenti feltételeknek megfelelő részatomot, % és annak kezdő indexpozicióját is (1-től számozva)! Visszalépéskor % legyen hajlandó az összes ilyen részatomot felsorolni! % % szava(Atom, Szo, Index): Az Atom atomban az Index kezdőpozición a Szo % % áll, amely csupa kisbetűből álló maximális, legalább kétbetűs atom. % % :- pred szava(atom::in, atom::out, int::out). % | ?- szava('a gyogy* 6ott', S, I). % I = 3, S = gyogy; I = 11, S = ott; no szava1(Atom, Szo, I) :- atom_codes(Atom, L), kodlista_szava(L, SzL, 1, I), atom_codes(Szo, SzL). % kodlista_szava(KL, SL, I0, I): a KL kódlistának az SL lista egy maximális, % maximális, legalább kételemű, csupa kisbetűből álló, az (I-I0+1)-edik pozíción % kezdődő folytonos része (a lista első eleme az 1. pozíción van). kodlista_szava([K|L], SzL, I0, I) :- kisbetu(K), max_szo(L, SzL1, M), !, ( SzL = [K|SzL1], I = I0 ; length(SzL1, Len), I1 is I0+Len+1, kodlista_szava(M, SzL, I1, I) ). kodlista_szava([_|L], SzL, I0, I) :- I1 is I0+1, kodlista_szava(L, SzL, I1, I). szava2(Atom, Szo, I) :- atom_codes(Atom, L), SzL = [_,_|_], append(L1, L2, L), append(SzL, L3, L2), forall(member(X,SzL), kisbetu(X)), \+ (last(L1, K), kisbetu(K)), \+ (L3 = [K|_], kisbetu(K)), length(L1, I0), I is I0+1, atom_codes(Szo, SzL). % Írjon Prologban egy olyan eljárást, amely egy tetszőleges Prolog struktúra- % kifejezés összes olyan valódi részstruktúráját felsorolja, amelynek neve % megegyezik az egész kifejezés nevével. Nem számít valódi részstruktúrának % maga az egész kifejezés, és a benne előforduló atomok. Vigyázat, a % kifejezésben változók is előfordulhatnak! % % nevu_resze(Kif, Resz): Resz a Kif-nek olyan valódi részstruktúrája, % % amelynek neve megegyezik Kif nevével. % % :- pred nevu_resze(any::in, any::out). % Példa: % | ?- nevu_resze(f(1,f(2), f(f(X)), g(f)), R). % R = f(2); R = f(f(X)); R = f(X) nevu_resze(K, R) :- compound(K), functor(K, Nev, _), nevu_resze(K, Nev, R). % K egy struktúrakifejezés, R annak valódi részstruktúrája, melynek neve Nev. nevu_resze(K, Nev, R) :- K =.. [_|Args], member(Arg, Args), compound(Arg), ( functor(Arg, Nev, _), R = Arg ; nevu_resze(Arg, Nev, R) ).