Přeskočit na obsah

Prolog

Zde je 10 rozsáhlých příkladů kódu v Prologu, které by mohly být zajímavé a poučné pro studenty:


1. Systém pro doporučení volnočasových aktivit (Volnočasové aktivity)

Tento kód pomáhá uživateli vybrat volnočasovou aktivitu na základě jeho zájmů a preferencí. Ukazuje použití faktů, pravidel a dotazů pro rozhodování.

Prolog

% Fakta o aktivitách a jejich charakteristikách
aktivita(čtení, klidné).
aktivita(čtení, intelektuální).
aktivita(turistika, aktivní).
aktivita(turistika, venkovní).
aktivita(programování, intelektuální).
aktivita(programování, kreativní).
aktivita(malování, kreativní).
aktivita(malování, klidné).
aktivita(sport, aktivní).
aktivita(sport, venkovní).
aktivita(vaření, kreativní).
aktivita(vaření, praktické).

% Pravidla pro určení vhodné aktivity
vhodná_aktivita(Aktivita, Zájem1) :-
    aktivita(Aktivita, Zájem1).

vhodná_aktivita(Aktivita, Zájem1, Zájem2) :-
    aktivita(Aktivita, Zájem1),
    aktivita(Aktivita, Zájem2).

doporučit_aktivitu :-
    write('Jaké jsou vaše zájmy? (například: klidné, aktivní, intelektuální, kreativní, venkovní, praktické)'), nl,
    read(Zájem1),
    (   vhodná_aktivita(Aktivita, Zájem1)
    ->  write('Možná se vám bude líbit: '), write(Aktivita), nl,
        write('Máte ještě nějaký zájem? (a/n)'), nl,
        read(Odpověď),
        (   Odpověď = a
        ->  read(Zájem2),
            (   vhodná_aktivita(Aktivita2, Zájem1, Zájem2)
            ->  write('Na základě dvou zájmů by se vám mohlo líbit: '), write(Aktivita2), nl
            ;   write('Nenašla jsem aktivitu odpovídající oběma zájmům. Zkuste jen jeden zájem.'), nl
            )
        ;   true
        )
    ;   write('Nenašla jsem aktivitu odpovídající tomuto zájmu. Zkuste jiné možnosti.'), nl
    ).

% Příklad dotazu:
% ?- doporučit_aktivitu.

2. Plánovač výletů s preferencemi (Plánovač výletů)

Tento kód pomáhá naplánovat výlet, s ohledem na typ dovolené (plážová, horská, městská) a rozpočet.

Prolog

% Fakta o místech a jejich charakteristikách
místo(paříž, městský, evropa, drahé).
místo(ří, městský, evropa, drahé).
místo(bali, plážový, asie, střední).
místo(thajsko, plážový, asie, střední).
místo(švýcarsko, horský, evropa, velmi_drahé).
místo(krkonoše, horský, evropa, levné).
místo(praha, městský, evropa, střední).
místo(turecko, plážový, evropa, střední).

% Pravidla pro nalezení místa
najdi_místo(Místo, TypDovolené, Rozpočet) :-
    místo(Místo, TypDovolené, _, Rozpočet).

najdi_místo(Místo, TypDovolené, Rozpočet, Region) :-
    místo(Místo, TypDovolené, Region, Rozpočet).

plánovat_výlet :-
    write('Jaký typ dovolené vás zajímá? (plážový, horský, městský)'), nl,
    read(TypDovolené),
    write('Jaký máte rozpočet? (levné, střední, drahé, velmi_drahé)'), nl,
    read(Rozpočet),
    (   najdi_místo(Místo, TypDovolené, Rozpočet)
    ->  write('Doporučené místo: '), write(Místo), nl,
        write('Chtěli byste zvážit konkrétní region? (a/n)'), nl,
        read(Odpověď),
        (   Odpověď = a
        ->  write('Jaký region? (evropa, asie)'), nl,
            read(Region),
            (   najdi_místo(Místo2, TypDovolené, Rozpočet, Region)
            ->  write('V tomto regionu by se vám mohlo líbit: '), write(Místo2), nl
            ;   write('Nenašel jsem vhodné místo v tomto regionu.'), nl
            )
        ;   true
        )
    ;   write('Nenašel jsem vhodné místo s zadanými parametry.'), nl
    ).

% Příklad dotazu:
% ?- plánovat_výlet.

3. Jednoduchý diagnostický systém pro počítače (Diagnostika počítače)

Tento kód simuluje jednoduchý expertní systém pro diagnostiku běžných problémů s počítačem.

Prolog

% Fakta o symptomech a jejich možných příčinách
symptom(žádný_obraz, monitor_vypnutý).
symptom(žádný_obraz, kabel_nepřipojen).
symptom(žádný_obraz, grafická_karta_vadná).
symptom(žádný_zvuk, reproduktory_vypnuté).
symptom(žádný_zvuk, chybí_ovladače_zvuku).
symptom(žádný_zvuk, zvuková_karta_vadná).
symptom(pomalý_chod, mnoho_spuštěných_programů).
symptom(pomalý_chod, málo_ram).
symptom(pomalý_chod, virus).
symptom(počítač_se_nezapne, bez_napájení).
symptom(počítač_se_nezapne, zdroj_vadný).

% Pravidla pro diagnostiku
diagnostikovat(Problém) :-
    write('Popište symptom: '), nl,
    read(Symptom),
    (   symptom(Symptom, Problém)
    ->  write('Možná příčina: '), write(Problém), nl,
        navrhnout_řešení(Problém)
    ;   write('Nemohu diagnostikovat tento symptom. Zkuste jiný.'), nl
    ).

navrhnout_řešení(monitor_vypnutý) :-
    write('Zkontrolujte, zda je monitor zapnutý a připojený do zásuvky.'), nl.
navrhnout_řešení(kabel_nepřipojen) :-
    write('Zkontrolujte připojení kabelu monitoru k počítači.'), nl.
navrhnout_řešení(grafická_karta_vadná) :-
    write('Možná je třeba vyměnit grafickou kartu. Obraťte se na specialistu.'), nl.
navrhnout_řešení(reproduktory_vypnuté) :-
    write('Zkontrolujte, zda jsou reproduktory zapnuté a správně připojené.'), nl.
navrhnout_řešení(chybí_ovladače_zvuku) :-
    write('Nainstalujte nebo aktualizujte ovladače zvukové karty.'), nl.
navrhnout_řešení(zvuková_karta_vadná) :-
    write('Možná je třeba vyměnit zvukovou kartu. Obraťte se na specialistu.'), nl.
navrhnout_řešení(mnoho_spuštěných_programů) :-
    write('Zavřete nepotřebné programy a restartujte počítač.'), nl.
navrhnout_řešení(málo_ram) :-
    write('Zvažte přidání více operační paměti (RAM).'), nl.
navrhnout_řešení(virus) :-
    write('Spusťte antivirovou kontrolu.'), nl.
navrhnout_řešení(bez_napájení) :-
    write('Zkontrolujte, zda je počítač připojen k elektrické síti.'), nl.
navrhnout_řešení(zdroj_vadný) :-
    write('Možná je vadný zdroj. Obraťte se na specialistu.'), nl.

% Příklad dotazu:
% ?- diagnostikovat(Problém).

4. Rodokmen a vztahy (Rodokmen)

Tento příklad demonstruje, jak Prolog efektivně pracuje s hierarchickými daty a vztahy.

Prolog

% Fakta o rodičovství
rodič(jana, petr).   % Jana je rodič Petra
rodič(jana, eva).    % Jana je rodič Evy
rodič(tomáš, petr).
rodič(tomáš, eva).
rodič(petr, alena).
rodič(petr, karel).
rodič(eva, lenka).
rodič(martin, lenka).
rodič(alena, david).

% Pravidla pro definování vztahů
muž(tomáš).
muž(petr).
muž(karel).
muž(martin).
muž(david).

žena(jana).
žena(eva).
žena(alena).
žena(lenka).

otec(Otec, Dítě) :-
    muž(Otec),
    rodič(Otec, Dítě).

matka(Matka, Dítě) :-
    žena(Matka),
    rodič(Matka, Dítě).

sourozenec(Sourozenec1, Sourozenec2) :-
    rodič(Rodič, Sourozenec1),
    rodič(Rodič, Sourozenec2),
    Sourozenec1 \= Sourozenec2.

dědeček(Dědeček, Vnouče) :-
    rodič(Dědeček, RodičDítěte),
    rodič(RodičDítěte, Vnouče),
    muž(Dědeček).

babička(Babička, Vnouče) :-
    rodič(Babička, RodičDítěte),
    rodič(RodičDítěte, Vnouče),
    žena(Babička).

předek(Předek, Potomek) :-
    rodič(Předek, Potomek).
předek(Předek, Potomek) :-
    rodič(Předek, MeziPotomek),
    předek(MeziPotomek, Potomek).

% Příklad dotazů:
% ?- otec(X, alena).
% ?- sourozenec(petr, X).
% ?- dědeček(X, david).
% ?- předek(jana, lenka).

5. Správce úkolů s prioritami a termíny (Správce úkolů)

Tento kód demonstruje správu úkolů s přiřazenými prioritami a termíny dokončení.

Prolog

% Fakta o úkolech (Název, Priorita, Termín)
úkol(projekt_matematiky, vysoká, 2025-06-25).
úkol(nákup_potravin, střední, 2025-06-20).
úkol(úklid_pokoje, nízká, 2025-06-22).
úkol(prezentace_dějepis, vysoká, 2025-06-28).
úkol(volat_babičce, nízká, 2025-06-19).

% Pravidla pro práci s úkoly
úkoly_podle_priority(Priorita, SeznamÚkolů) :-
    findall(Úkol, úkol(Úkol, Priorita, _), SeznamÚkolů).

úkoly_před_datem(Datum, SeznamÚkolů) :-
    findall(Úkol, (úkol(Úkol, _, Termín), Termín @=< Datum), SeznamÚkolů).

přidat_úkol(Název, Priorita, Termín) :-
    assertz(úkol(Název, Priorita, Termín)).

smazat_úkol(Název) :-
    retract(úkol(Název, _, _)).

zobrazit_všechny_úkoly :-
    forall(úkol(Název, Priorita, Termín),
           (write('Úkol: '), write(Název),
            write(', Priorita: '), write(Priorita),
            write(', Termín: '), write(Termín), nl)).

% Příklad dotazů:
% ?- úkoly_podle_priority(vysoká, Úkoly).
% ?- úkoly_před_datem(2025-06-22, Úkoly).
% ?- přidat_úkol(naučit_se_prolog, vysoká, 2025-07-01).
% ?- zobrazit_všechny_úkoly.
% ?- smazat_úkol(nákup_potravin).

6. Generátor jednoduchých vět (Generátor vět)

Tento kód ukazuje, jak Prolog může být použit pro generování textu na základě gramatických pravidel.

Prolog

% Slovník
člen(jedna).
člen(nějaká).
člen(ten).
člen(ta).
člen(to).

podstatné_jméno(chlapec).
podstatné_jméno(dívka).
podstatné_jméno(pes).
podstatné_jméno(kočka).
podstatné_jméno(strom).

sloveso(běží).
sloveso(jí).
sloveso(spí).
sloveso(vidí).
sloveso(čte).

přídavné_jméno(velký).
přídavné_jméno(malý).
přídavné_jméno(rychlý).
přídavné_jméno(líný).
přídavné_jméno(zelený).

předložka(na).
předložka(v).
předložka(pod).
předložka(vedle).

% Pravidla pro strukturu vět
věta(Slovo1, Slovo2, Slovo3, Slovo4, Slovo5) :-
    člen(Slovo1),
    přídavné_jméno(Slovo2),
    podstatné_jméno(Slovo3),
    sloveso(Slovo4),
    předložka(Slovo5). % Zde by se dalo rozšířit o předložkovou frázi atd.

generuj_větu :-
    findall([C, P, PN, S, Předl], (člen(C), přídavné_jmé(P), podstatné_jmé(PN), sloveso(S), předložka(Předl)), Věty),
    random_member(Věta, Věty),
    write_list(Věta).

write_list([]).
write_list([H|T]) :-
    write(H), write(' '),
    write_list(T).

% Příklad dotazu:
% ?- generuj_větu.

7. Jednoduchý systém pro správu inventáře (Správce inventáře)

Tento kód demonstruje správu inventáře položek s jejich množstvím a umístěním.

Prolog

% Fakta o inventáři (Položka, Množství, Umístění)
položka(tužka, 100, kancelář).
položka(papír, 50, sklad).
položka(sešit, 75, kancelář).
položka(kalkulačka, 10, kancelář).
položka(židle, 5, sklad).

% Pravidla pro práci s inventářem
zjistit_množství(Položka, Množství) :-
    položka(Položka, Množství, _).

najít_položky_v_umístění(Umístění, SeznamPoložek) :-
    findall(P, (položka(P, _, Umístění)), SeznamPoložek).

přidat_položku(Položka, Množství, Umístění) :-
    assertz(položka(Položka, Množství, Umístění)).

odebrat_položku(Položka) :-
    retract(položka(Položka, _, _)).

aktualizovat_množství(Položka, NovéMnožství) :-
    retract(položka(Položka, StaréMnožství, Umístění)),
    assertz(položka(Položka, NovéMnožství, Umístění)).

zobrazit_inventář :-
    forall(položka(Položka, Množství, Umístění),
           (write('Položka: '), write(Položka),
            write(', Množství: '), write(Množství),
            write(', Umístění: '), write(Umístění), nl)).

% Příklad dotazů:
% ?- zjistit_množství(tužka, M).
% ?- najít_položky_v_umístění(kancelář, Položky).
% ?- přidat_položku(fixa, 20, kancelář).
% ?- aktualizovat_množství(papír, 40).
% ?- zobrazit_inventář.

8. Rozhodovací systém pro volbu jídel (Volba jídla)

Tento kód pomáhá vybrat jídlo na základě preferencí (např. vegetariánské, masové, rychlé).

Prolog

% Fakta o jídlech a jejich charakteristikách
jídlo(smažený_sýr, vegetariánské, rychlé, české).
jídlo(guláš, masové, pomalé, české).
jídlo(salát_caesar, masové, rychlé, mezinárodní).
jídlo(čočka_s_vejcem, vegetariánské, střední, české).
jídlo(pizza, vegetariánské, rychlé, italské).
jídlo(pizza, masové, rychlé, italské). % Pizza může být i masová

% Pravidla pro doporučení jídla
doporučit_jídlo(Jídlo, Typ) :-
    jídlo(Jídlo, Typ, _, _).

doporučit_jídlo(Jídlo, Typ, DobaPřípravy) :-
    jídlo(Jídlo, Typ, DobaPřípravy, _).

doporučit_jídlo_dialog :-
    write('Jaký typ jídla preferujete? (vegetariánské, masové)'), nl,
    read(TypJídla),
    (   doporučit_jídlo(Jídlo, TypJídla)
    ->  write('Možná se vám bude líbit: '), write(Jídlo), nl,
        write('Záleží vám na době přípravy? (a/n)'), nl,
        read(Odpověď),
        (   Odpověď = a
        ->  write('Jaká doba přípravy? (rychlé, střední, pomalé)'), nl,
            read(DobaPřípravy),
            (   doporučit_jídlo(Jídlo2, TypJídla, DobaPřípravy)
            ->  write('S ohledem na čas, zkuste: '), write(Jídlo2), nl
            ;   write('Nenašel jsem vhodné jídlo s těmito parametry.'), nl
            )
        ;   true
        )
    ;   write('Nenašel jsem vhodné jídlo pro tento typ.'), nl
    ).

% Příklad dotazu:
% ?- doporučit_jídlo_dialog.

9. Jednoduchý systém pro rezervaci pokojů (Rezervace pokojů)

Tento kód spravuje dostupnost pokojů a umožňuje jednoduchou rezervaci.

Prolog

% Fakta o pokojích (Číslo pokoje, Typ, Cena za noc, Dostupný)
pokoj(101, jednolůžkový, 1000, ano).
pokoj(102, dvoulůžkový, 1500, ano).
pokoj(103, apartmá, 3000, ano).
pokoj(104, jednolůžkový, 1100, ano).
pokoj(105, dvoulůžkový, 1600, ne). % Tento pokoj je obsazen

% Pravidla pro rezervaci a správu
dostupný_pokoj(Číslo, Typ, Cena) :-
    pokoj(Číslo, Typ, Cena, ano).

rezervovat_pokoj(ČísloPokoje) :-
    retract(pokoj(ČísloPokoje, Typ, Cena, ano)),
    assertz(pokoj(ČísloPokoje, Typ, Cena, ne)),
    write('Pokoj '), write(ČísloPokoje), write(' byl úspěšně rezervován.'), nl.

uvolnit_pokoj(ČísloPokoje) :-
    retract(pokoj(ČísloPokoje, Typ, Cena, ne)),
    assertz(pokoj(ČísloPokoje, Typ, Cena, ano)),
    write('Pokoj '), write(ČísloPokoje), write(' byl uvolněn.'), nl.

najít_dostupné_pokoje(Typ, SeznamDostupných) :-
    findall([Číslo, Cena], dostupný_pokoj(Číslo, Typ, Cena), SeznamDostupných).

zobrazit_stav_pokojů :-
    forall(pokoj(Číslo, Typ, Cena, Stav),
           (write('Pokoj: '), write(Číslo),
            write(', Typ: '), write(Typ),
            write(', Cena: '), write(Cena),
            write(', Stav: '), write(Stav), nl)).

% Příklad dotazů:
% ?- najít_dostupné_pokoje(jednolůžkový, Pokoje).
% ?- rezervovat_pokoj(101).
% ?- zobrazit_stav_pokojů.
% ?- uvolnit_pokoj(105).

10. Systém pro doporučení knih na základě žánru a oblíbenosti (Doporučovač knih)

Tento kód pomáhá studentům najít knihy, které by je mohly zajímat, s ohledem na žánr a hodnocení.

Prolog

% Fakta o knihách (Název, Autor, Žánr, Hodnocení, Rok vydání)
kniha('Harry Potter', 'J.K. Rowling', fantasy, 9.5, 1997).
kniha('Malý princ', 'Antoine de Saint-Exupéry', filozofická, 9.8, 1943).
kniha('Hobit', 'J.R.R. Tolkien', fantasy, 9.0, 1937).
kniha('Stopařův průvodce po Galaxii', 'Douglas Adams', sci_fi, 9.2, 1979).
kniha('Babička', 'Božena Němcová', klasika, 8.5, 1855).
kniha('Krvavý román', 'Josef Váchal', horor, 8.0, 1924).

% Pravidla pro doporučení
doporučit_podle_žánru(Žánr, SeznamKnih) :-
    findall(Název, (kniha(Název, _, Žánr, _, _)), SeznamKnih).

doporučit_nejlepší_v_žánru(Žánr, Kniha) :-
    findall([Hodnocení, Název], (kniha(Název, _, Žánr, Hodnocení, _)), SeznamHodnocení),
    keysort(SeznamHodnocení, Seřazené), % Seřadí podle hodnocení
    reverse(Seřazené, SeřazenéReversed), % Od nejvyššího po nejnižší
    [_, Kniha] = SeřazenéReversed. % Vezme první knihu s nejvyšším hodnocením (první z obráceného seznamu)

doporučit_knihu_dialog :-
    write('Jaký žánr vás zajímá? (fantasy, filozofická, sci_fi, klasika, horor)'), nl,
    read(Žánr),
    (   doporučit_podle_žánru(Žánr, Knihy)
    ->  write('Knihy v tomto žánru: '), write(Knihy), nl,
        write('Chtěli byste nejlépe hodnocenou knihu v tomto žánru? (a/n)'), nl,
        read(Odpověď),
        (   Odpověď = a
        ->  doporučit_nejlepší_v_žánru(Žánr, NejlepšíKniha),
            write('Nejlépe hodnocená kniha v žánru '), write(Žánr), write(': '), write(NejlepšíKniha), nl
        ;   true
        )
    ;   write('Neznám knihy v tomto žánru.'), nl
    ).

% Příklad dotazů:
% ?- doporučit_podle_žánru(fantasy, Knihy).
% ?- doporučit_nejlepší_v_žánru(klasika, Kniha).
% ?- doporučit_knihu_dialog.