Priprava okolja

Dodatne "on-line" vaje iz prologa

Te naloge najdete tukaj: https://codeq.si/?s=prolog. Naredite si nov račun.

Družinske relacije

V tem sklopu nalog bomo definirali predikate za nekaj družinskih relacij, kot so »sestra«, »teta« in »prednik«. Za preizkušanje rešitev bomo uporabljali družinsko drevo (pravzaprav gozd), ki ga najdete na učilnici.

Družinska drevesa

Družinske relacije v prologu opišemo s predikati parent/2, male/1 in female/1. Zapis parent/2 pomeni, da gre za predikat z imenom parent z dvema argumentoma. Primer:

    parent(tina, william).
    parent(thomas, william).
    parent(thomas, sally).
    …
    female(tina).
    female(sally).
    female(vanessa).
    …
    male(william).
    male(thomas).
    male(jeffrey).
    …

Dejstvo parent(tina, william) pomeni, da je tina starš od williama. Imena pišemo z malimi črkami, ker bi jih prolog sicer obravnaval kot spremenljivke.

Datoteko famrel.pl v prolog naložimo z ukazom

    ?- ['famrel.pl'].

Nato lahko pišemo različne poizvedbe, npr.:

    ?- parent(thomas, sally).
    true.
    ?- parent(thomas, X).
    X = william ;
    X = sally .

S podpičjem (;) oziroma n zahtevamo naslednjo rešitev, s piko (.) pa poizvedbo prekinemo. Če se poizvedba ne ustavi, jo prekinemo s ctrl-c in nato a (za abort).

mother/2

Definirajte predikat mother(X, Y), ki velja, ko je X mama od Y.

    ?- mother(tina, william).
    true.
    ?- mother(nevia, Y).
    Y = luana ;
    Y = daniela.

grandparent/2

Definirajte predikat grandparent(X, Y), ki velja, ko je X stari starš od Y.

    ?- grandparent(tina, vanessa).
    true.
    ?- grandparent(tina, Y).
    Y = vanessa ;
    Y = patricia.

sister/2

Definirajte predikat sister(X, Y), ki velja, ko je X sestra od Y.

    ?- sister(vanessa, Y).
    Y = patricia.

Namig: s predikatom dif/2 povemo prologu, da sta (oz. naj bosta) dve vrednosti različni. Na primer:

    ?- dif(X, 2), X = 3.
    X = 3.
    ?- dif(X, 2), X = 2.
    false.

aunt/2

Definirajte predikat aunt(X, Y), ki velja, ko je X teta od Y.

    ?- aunt(sally, Y).
    Y = vanessa ;
    Y = patricia.

ancestor/2

Definirajte predikat ancestor(X, Y), ki velja, ko je X prednik (starš / stari starš / …) od Y.

    ?- ancestor(patricia, Y).
    Y = john ;
    Y = michael ;
    Y = michelle.

descendant/2

Definirajte predikat descendant(X, Y), ki velja, ko je X potomec (otrok / vnuk / …) od Y.

    ?- descendant(patricia, Y).
    Y = william ;
    Y = tina ;
    Y = thomas.

Seznami

Sezname v prologu pišemo z oglatimi oklepaji:

    ?- L = [1,2,3,4].

in lahko vsebujejo karkoli:

    ?- L = [1, a, foo(4,5), [a,b,c], 3.14].

Z združevanjem lahko v seznamu dostopamo do glave (prvega elementa) in repa (preostanka seznama):

    ?- [H|T] = [1,2,3,4].
    H = 1,
    T = [2,3,4].

Seveda deluje tudi obratno:

    ?- H = 1, T = [2,3,4], L = [H|T].
    L = [1,2,3,4].

Dva poljubna seznama lahko staknemo s predikatom append/3:

    ?- append([1,2], [3,4], L).
    L = [1,2,3,4].

Seveda deluje tudi obratno ~ poiščemo lahko A in B, ki se stakneta v dani seznam:

    ?- append(A, B, [1,2,3]).
    A = [],
    B = [1, 2, 3] ;
    A = [1],
    B = [2, 3] ;
    A = [1, 2],
    B = [3] ;
    A = [1, 2, 3],
    B = [].

ancestor/3

Definirajte predikat ancestor(X, Y, L), ki deluje enako kot ancestor/2, le da vrne še seznam oseb na poti od X do Y.

    ?- ancestor(thomas, vanessa, L).
    L = [thomas, william, vanessa].
    ?- ancestor(thomas, _, L).
    L = [thomas, william] ;
    L = [thomas, sally] ;
    L = [thomas, jeffrey] ;
    L = [thomas, william, vanessa] ;
    L = [thomas, william, patricia] ;
    L = [thomas, william, vanessa, susan] ;
    L = [thomas, william, patricia, john] ;

Kako bi s pomočjo predikata ancestor/3 definirali predikata grandparent/2 in ancestor/2?

member/2

Definirajte predikat member(X, L), ki velja, ko je X element seznama L.

    ?- member(X, [1,2,3]).
    X = 1 ;
    X = 2 ;
    X = 3.
    ?- member(1, [3,2,X]).
    X = 1.

insert/3

Definirajte predikat insert(X, L1, L2), ki velja, ko seznam L2 dobimo tako, da v L1 vstavimo X na poljubno mesto.

    ?- insert(1, [2,3], L).
    L = [1,2,3] ;
    L = [2,1,3] ;
    L = [2,3,1].

reverse/2

Definirajte predikat reverse(A, B), ki velja, ko vsebuje seznam B elemente seznama A v obratnem vrstnem redu.

    ?- reverse([1,2,3], X).
    X = [3,2,1].
    ?- reverse([], []).
    true.
Zadnja sprememba: sreda, 3. maj 2023, 14.02