FLP studentská sbírka úloh
Přehlednější sbírka oficiálních řešení + zadání z fitušky od studentů.
Upravujte, přidávejte dle libosti. Držte pls nějakou strukturu, ať se v tom dá vyznat a nedopadne to jak sdílený dokument. Pro diskuzi se dají použít komentáře u odstavců/kódů.
- Haskell časť je za 30b a Prolog časť za 30b
- LEN na riadnom termíne je vždy bonus +10b
- nie každý termín obsahuje dôkaz či Lambda kalkul
Haskell
2022/2023
Předtermín
-
Lambda kalkul: zadefinujte jakkoliv True, False a XOR (pripadne cokoliv dalsiho je potreba). Ukazte, ze XOR T F -> T (7b)
-
V haskellu je dano
suma a [] = a
suma a (x:xs) = suma (a + x) xs
Dokazte, ze suma 0 xs = foldl (+) 0 xs
. Byla tam poznamka, ze mame vhodne zvolit indukcni hypotezu (8b)
-
Zadefinujte datovy typ pro vyrazy s celymi cisly, jejich scitanim a nasobenim (2b)
-
Nadefinujte akci pp
(pretty-print) prijimajici argument odpovidajici typu z ulohy 3, co na standardni vystup vypise vyraz uzavorkovany tak, aby vyznam zustal zachovan (nesmi ale byt zadne zavorky navic). Mohli jsme pouzit Prelude a navic putChar
, putStr
. Na pomocnem papire bylo asi 5 prikladu uzavorkovani, neco jako: (13b)
- Premie: Nadefinovat typ pro double linked list (2b). Napsat funkci
l2dll
, co vezme bezny haskellovsky seznam a udela z nej ten nas DLL (8b).
2021/2022
termin

Vlastnosť operátoru pevného bodu – Y E = E (Y E)
Definícia LT v λ-kalkule s použitím operátora pevného bodu (Y
), iszero
a prev
:
- funkce mid, která pro vstupní seřaditelný seznam vrací takovou hodnotu, která seznam rozdělí na dvě části, kde jedna obsahuje pouze menší prvky, druhá pouze větší prvky a jejichž délka se liší nanejvýš o 1.
Nebylo ale v zadání zmíněno, zda musí být prvky v seznamu unikátní. Pokud by nebyly, imo nebude řešení existovat.
K dispozici afaik holý Haskell.
alebo
- Haskell io
Načíst soubor a vypsat jej, přičemž každý řádek je trimmed o whitespaces (funkce trim k dispozici) a před každým řádkem je jeho počet znaků po trimu.
Např.: " Hello " -> "5:Hello"
Za takto upraveným vypsaným souborem přidat
(Počet řádků celkem) ++ "/" ++ (počet po trimu prázdných řádků)
Např.: "1/0"
K dispozici klasické IO funkce, Prelude (unlines/lines, …), byly k nim i signatury.
Riadny
- Definuj štruktrúru zásobníka pre riešenie v konštantnom čase (tj. bez rekurzie)
empty
- inicializuje prázdny zásobnik
top
- vráti vrchol zásobnika
push
- pridá položku na vrchol zásobnika
pop
- odstráni vrch zásobníka
len
- vráti počet položiek v zásobníku
- definovať funkcie
- pushStr, ktorá vloží reťazec na zásobník
- popStr, ktorá popne reťazec zo zásobníka ak sa zhoduje
alternatívna implementácia
- definovať dátovú štruktúru pre reprezentáciu pravidiel deterministického konečného automatu
- IO úloha - spracovat súbor do vnútornej reprezentacie pravidiel (štruktúry z predchádzajúcej úlohy)
Bonus: isRuleApplicable - najst pravidlo ktore je aplikovatelné pre determinitický konecný automat + napísať štruktúru
1. opravný
Implementovať IO funkciu, ktorá spojí nasledujúce riadky ak ich dĺžka dokopy je menej, rovná 120. Tieto riadky očísluje na zaciatku, prida dvojbodku a pridá obsah spojených riadkov. Spojené riadky zapíse do súboru fileinput s koncovkou .out
2020/2021
Riadny
- zadefinovať datovy typ pre aritmeticke operacie +/-
- spraviť funkciu eval pre vyhodnocovanie arit. operacii + a -
- funkcia load, načítať zo subora v tvare prefix operacii do datoveho typu
napr. + 4 2
alebo to bolo možno so zatvorkami +(4 2)
(malo by to byť jedno v podstate)
1. opravný
- LE datova struktura
iné riesenie - 19/20 1. op
Konkrétny priklad
\x.xy
= Abs (x) (App (Var x) (Var y))
\xy.x(xy) = (\x.(\y.x(xy)))
= Abs (x) (Abs (y) (App (Var x) (App (Var x) (Var y))))
- union, intersection, delete
- fv - Vytvorenie zoznamu voľných premenných v lambda výraze
riesenie
isApp E X F
- ci je beta redukcia F
za X
aplikovatelna vo vyraze E
, tak True
- isValid
riesenie
alebo
- print suboru s tym ze sa na zaciatku pridaju cisla zarovnane vpravo
napr.:
výstup:
2. opravný termín
/6b/ Definovať funkciu suf
, ktorá prijíma ako argument zoznam a vracia zoznam všetkých sufixov tohto zoznamu. Definovať funkciu pre
, ktorá prijíma ako argument zoznam a vracia zoznam všetkých prefixov tohto zoznamu. Funkcia pre
musí korektne fungovať aj pre nekonečné zoznamy, t.j. take 10 $ pre [1..]
vráti zoznam desiatich zoznamov.
/4b/ Definovať funkciu substrs
, ktorá prijíma ako argument reťazec a vracia zoznam všetkých podreťazcov tohto reťazca. Definovať funkciu subsets
, ktorá prijíma ako argument reťazec a vracia zoznam všetky kombinácie tohto reťazca. Môžte použiť aj funkcie suf
a pref
z predošlej úlohy.
/6b/ Definovať funkciu ff
, prvý argument je meno súboru v ktorom je každý riadok vo formáte <key>:<value>
a druhý argument je hľadaný klúč. Funkcia ff
vráti hodnotu tohto klúča. Ak sa daný klúč v súbore nenachádza, funkcia vráti, že zadaný klúč nenašiel.
2019/2020
Předtermín
Definovat datovou strukturu, která reprezentuje neorientovaný graf (prostě množina vrcholů a množina hran, kde hrana je dvojice - vrchol, vrchol).
Vytvořit funkci, co maže izolované uzly v neorientovaném grafu:
Dán typ pro neorientovaný graf, soubor, v něm po řádcích jména uzlů, volný řádek, dvojice jmen oddělených dvojtečkou dává hrany.
Zkontrolovat funkcí checkUG, zda-li je to jinak korektní graf. Vrátit graf.
Alebo
Řádný termín
Dáno (CS - context sensitive grammar):
Úkoly:
1. opravný termín
/3b/ Funkcie na prienik a zjednotenie množín v čistom Haskelli. Jedna musela byť napísaná s využitím generátorov zoznamov a druhá iným spôsobom.
/2b/ Datová štruktúra pre lambda výrazy.
iné riesenie - 20/21 1. op
/4b/ Vytvorenie zoznamu voľných premenných v lambda výraze
/8b/ …
/6b/ Niečo s leftmost outermost deriváciou/aplikáciou
2018/2019
Řádný termín
- Nadefinovat strukturu pre DirTree.
- Urobit funkciu, ktora spocita velkost obsahu složky.
- Urobit funkciu ktora vrati zoznam suborov a složek, ktory obsahuju zadany prefix.
- Funkcia na rekurzivny vypis obsahu priecinka, nieco ako:
1. Opravný termín
2-6) Pomocí haskell implementovat lambda výrazy a nějakou práci nad nima, myslím, že tam byl substr
2. Opravný termín
- Nadefinovat typ BTree, který má předem daný počet potomků a předem zadanou hloubku stromu (zadáno při tvorbě). Listy mají jako hodnotu seznam dvojic (klíč, hodnota), které jsou předem neznámého typu. Uzly mají pak jako hodnotu seznam, který odpovídá potomkům a v každá hodnota v seznamu značí maximální klič, který může daný potomek obsahovat.
- Vytvoření funkce
create :: Integer -> Integer -> Int -> Int -> BTree
. Kde parametry jsou po sobě: Max klíč, min klíč, hloubka, počet potomků.
BONUS: za řešení, které se vypořádá s tím, když je počet potomků/pater nesoudělný s celkovým počtem klíčů.
- Vytvoření funkce
ins :: (typ neuveden)
, která dostává argumenty: klíč, data, strom a která podle zadaného klíče buď upraví hodnotu ve stromu, nebo ji přidá.
- Vytvoření funkce
allList :: (typ neuveden)
, která ze zadaného stromu vybere z listů všechny hodnoty a vrátí je jako jediný konkatenovaný seznam hodnot.
BONUS: pokud tato funkce bude pracovat s lineární časovou složitostí
2017/2018
Řádný termín
/4b/ Funkce sort v holem Haskellu, bere seznam hodnot nad tridou Ord a vraci serazene od nejmensiho po nejvetsi. K dispozici fold*, map a operace nad tridou Ord.
/13b/ Nadefinovat funkciu pt, ktora berie nazov suboru ako argument. Z tohoto suboru nacita zaznamy ve formatu Cislo_typu_Integer#String, pripadne prazdny riadok. Zaznam reprezentovat datovym typom DLog. Vypsat zaznamy s cisly, ktere jsou nasobkem 5 (cislo mod 5 == 0). Odelene budu tentoraz dvojbodkou (:).
Je potrebne uviest typove defincie pre kazdu pouzitu funkciu.
Zadane byly typove definicie nekterych funkci pro praci s IO (openFile, hGetContents, lines, unlines, ReadMode, WriteMode, atp.).
/6b/ BONUS otazka - Vytvorit datovou strukturu pro reprezentaci stromu. Vytvorit funkci initTree, ktera dostane jako parametr hodnotu a vytvori nekonecny strom, kde vsechny uzly obsahuji tuto hodnotu. Vytvorit funkci takeLev, ktera vrati strom az po urcitou uroven danou parametrem.
1. opravný termín
Vytvořit nekonečný seznam prvočísel.
Haskell s dostupnými IO funkcemi. Napsat funkci mkR
, která dostane jméno souboru. V řádcích souboru se nachází buď FIT login, nebo prázdný řádek, nebo nějaký jiný text. Funkce má vypsat nejdříve počet řádků s validními loginy, pak počet textových řádků, pak počet prázdných řádku a nakonec vypsat všechny tyto validní loginy v náhodném pořadí. Pro generování náhodných čísel je k dispozici funkce randomRIO :: Random a => (a, a) -> IO a
.
2016/2017
Řádný termín
Holý Haskell. Definovat datový typ pro asociativní pole. Dále napsat funkci test, která ověří, že klíče v asociativním poli jsou unikátní. (7b)
Haskell + prelude (kromě readFile) + nějaké IO funkce jako (hGetContents, hClose, openFile, hPutStr). Napsat funkci fdup, která načte soubor jehož nazev je v jejím parametru a potom tento soubor vypíše na výstup, ale s tím, že pokud jsou na začátku řádku dva znaky +, tak se tento řádek vypíše 2x, ale už bez těchto dvou plusových znaků. Nesmí se změnit pořadí řádků. (6b)
Bonus: Definujte strukturu pro termy v prologu a následně funkci unify s dvěma parametry, která vratí nejobecnější unifikátor dvou termu (8b)
Prolog
2022/2023
Řádný
Implementace funkce prime/1, která ověří, že X je prvočíslo a při zadání prime(X) generuje nekonečkou posloupnost prvočísel.
Předtermín
Implementace deterministickeho Turingova stroje. Je dano :- dynamic tol/1 tor/1 state/1 head/1.
, kde state je predikat reprezentujici aktualni stav Turingova stroje. head
obsahuje symbol pod hlavou. tol
obsahuje seznam reprezentujici pasku vlevo od hlavy. tor
stejne tak, ale vpravo od hlavy. V obou pripadech je prvni prvek seznamu policko pasky nejblize hlave. Semantika TM je klasicka, tj. neni mozne se posunout doleva, pokud seznam tol
je prazdny. Doprava je mozne se posunout vzdy (blank pod hlavou). Krok TS je reprezentovany termem move(State, Symbol, Action)
, kde State
je soucasny stav, Symbol
symbol pod hlavou a Action
akce, co se ma provest (viz 4).
V zadani zminoval, ze mame vzdy co nejvic vyuzivat predikaty vzdy z predchozich ukolu.
- Implementujte predikat
shl/0
, co pokud je to mozne, pak provede posun hlavy doleva a uspeje. (7b) V dalsich prikladech muzeme predpokladat existenci predikatu shr/0, co posouva doprava, wh/1, co zapisuje pod hlavu a rh/1, co cte symbol pod hlavou.
- Implementujte predikat
ttol/1
, co do prvniho argumentu vrati obsah cele pasky (5b za "oneliner", jinak 3b)
- Implementujte predikat findmove(Moves, Action), co ve vstupnim seznamu
Moves
(jeho obsah jsou termy move) najde proveditelnou akci a zunifikuje ji do argumentu Action
. Pak tam byla asi 4radkova poznamka o tom, ze v seznamu Moves muzou byt i kroky, ktery jdou provest s jakymkoliv symbolem apod, ale mame brat v potaz jen validni. Zaroven mame umoznit backtracking v pripade, ze tech validnich pohybu je vic (ze to v realu nenastane, ale mame to podporovat) (3b)
- Implementujte predikat action/1, ktery dostane jako argument akci a provede ji. Akce muze byt nasledujiciho tvaru (5b):
a) act(w, Sym, State)
- zapise Sym pod hlavu a presune se do stavu State
b) act(r, State)
- posune hlavu doprava a presune se do stavu State
c) act(l, State)
- posune hlavu doleva a presune se do stavu State
- Implementujte predikat work(Moves, InitState, Tape, FinalStates), ktery dostane mozne prechody TS
Moves
(viz format move
), pocatecni stav InitState
, seznam koncovych stavu FinalStates
a pocatecni obsah pasky Tape
a uspeje, pokud pro tohle zadani existuje reseni. Tim, ze je to deterministicky TM, mame uvazovat, ze je mozne provest vzdy maximalne jeden krok z Moves
, tj. neuvazovat backtracking. (10b)
2021/2022
1. termín
- [12b.]
Příklad[[1, 2], [2,3,4], []], [[3,4], [1], [1,2,3,4]]
Vstupem seznam množin,
Sjednocení všech množin tvoří univerzum,
Pro každou vstupní množinu vypsat doplněk vůči tomuto univerzu.
K dispozici holý prolog.
complements(I,O) :-
getUniverse(I,U),
getComplements(I,U,O)
.
getComplements([],_,[]).
getComplements([HI|TI],U,[HO|TO]) :-
getDifference(HI,U,HO),
getComplements(TI,U,TO)
.
getDifference(U,U,[]).
getDifference(_,[],[]).
getDifference(S,[HU|SU],[HU|R]) :-
notMember(HU,S),
getDifference(S,SU,R)
.
getDifference(S,[_|SU],R) :-
getDifference(S,SU,R)
.
getUniverse([],[]).
getUniverse([H|T],U) :-
getUniverse(T,TU),
append(H,TU,U)
.
notMember(_,[]).
notMember(X,[H|T]) :-
notMember(X,T),
X \= H
.
member(_,[]) :- false.
member(X,[X|_]).
member(X,[_|T]) :-
member(X,T)
.
append([],X,X).
append(X,[],X).
append(L1,L2,R) :-
appendInner(L1,L2,T),
removeDuplicates(T,R)
.
appendInner([],X,X).
appendInner(X,[],X).
appendInner([H1|T1],L,[H1|R]) :-
appendInner(T1,L,R)
.
removeDuplicates([],[]).
removeDuplicates([H|T],[H|R]) :-
notMember(H,T),
removeDuplicates(T,R)
.
removeDuplicates([_|T],R) :-
removeDuplicates(T,R)
.
- [4b.] splt
chová se jako span v Haskellu.
splt (P, A, AT, AF)
vstupem predikát P a seznam A.
Výstupem dva seznamy:
AT = souvislý prefix A, kde pro všechny prvky platí predikát P.
AF = zbytek seznamu A(od prvního prvku, kde P neplatí, do konce).
K dispozici holý prolog.
- [asi 6b.]
Vyhledání všech klíčů ve stromě, které se vážou k dané hodnotě.
Klíče ve stromě byly unikátní, hodnoty byly neznámého typu
// test příslušnosti do seznamu
elem(H, [H|_]) :- !.
elem(H, [_|T]) :-
elem(H, T),
!.
// sjednocení množin
union([], R, R) :- !.
union(R, [], R) :- !.
union([H|T], U, R) :-
elem(H, U),
union(T, U, R),
!.
union([H|T], U, [H|R]) :-
union(T, U, R),
!.
// definice stromu
// strom může být prázdný, to jsem vyjádřil predikátem myTree(stop).
myTree(stop).
// strom může mít tři položky
// -> dvojici (klíč, hodnota), to v prologu vyjádřím zápisem -(_K, _V), spojovník a závorky vyjadřuji, že je to dvojice, podtržítko na začátku vyjadřuje anonymitu.
// -> levý podstrom
// -> pravý podstrom
// musí nutně platit, že Left i Right jsou stromy.
myTree(tree(-(_Key, _Value), Left, Right)) :-
myTree(Left),
myTree(Right).
// hledání klíče dle libovolné hodnoty v prázdném stromě vrátí prázdný seznam jako odpověď
getKeysByValue(_, myTree(stop), []) :- !.
// při hledání klíčů dle hodnoty Val naunifikuji do A, B klíče odpovídající hodnotě Val z podstromů Left, Right (po řadě), sjednotím je do R a přidám k nim Key, pokud hodnota aktuálního uzlu odpovídá hledané hodnotě
getKeysByValue(Val, myTree(tree(-(Key, Value), Left, Right)), [Key|R]) :-
Val == Value,
getKeysByValue(Val, myTree(Left), A),
getKeysByValue(Val, myTree(Right), B),
union(A, B, R),
!.
Zkuste si třeba:
myTree(stop).
myTree(tree(-(1, 2), stop, tree(-(2, 3), stop, stop))).
getKeysByValue(2, myTree(tree(-(10,2), tree(-(1, 2), stop, stop), tree(-(100, 0), stop, tree(-(1000, 2), stop, stop)))), R).
--Nebo-------
union([], [], []).
union([], T, T).
union([H|T], S, [H|U]) :-
\+ member(H, S),
union(T, S, U).
union([H|T], S, U) :-
member(H, S),
union(T, S, U).
myTree(stop).
myTree(tree(-(_Key, _Value), Left, Right)) :-
myTree(Left),
myTree(Right).
getKeysByValue(_, stop, []) :- !.
getKeysByValue(Val, tree(-(Key, Value), Left, Right), R) :-
getKeysByValue(Val, Left, A),
getKeysByValue(Val, Right, B),
(Val == Value -> union(A, B, AB), union(AB, [Key], R) ; union(A, B, R)),
!.
main :-
union([1,2,3], [2,3,4], U1),
format('Test 1: Union = ~w~n', [U1]),
myTree(tree(-(1, a), tree(-(2, b), stop, stop), tree(-(3, c), stop, stop))),
format('Test 2: myTree passed~n'),
getKeysByValue(a, tree(-(1, a), tree(-(2, b), stop, stop), tree(-(3, a), stop, stop)), K1),
format('Test 3: Keys = ~w~n', [K1]),
halt.
- [asi 8b.]
~jsme v nekonečném stavovém prostoru, prakticky všechno je neznámé nebo dané parametrem a úkolem je udělat krok/cestu v rámci stavového prostoru … no idea
1. opravný
- vytvoriť funkciu notelem, ktorá failne ak sa polozka nachádza v zadanom liste notelem(+Val,+List).
- implementovat
keyval(Key, Val)
(cca 15b)
- pouzite assert, nonvar, var, !
- ak sú zadané key aj value skúsi vložiť do pamati
- ak sú zadany len key, nájde value z pamäti
- keyval(K, V) - vypíše z pamati
- remKey(Key) - odstráni Key z pamati, neuspeje ak nenájde, remAll - uspeje vždy raz, odstráni predikáty z pamäti
- vytvoriť zjednocovanie zanorenych listov do obycajného listu - zostanú len najvonkajšejšie zátvorky (najľavejšia+najpravejšia)
destr([[1,[]],[2,[3],4],[[], 5]],[1,2,3,4,5])
Riadny
Lambda calcul v prologu
fv(var(V),[V]).
fv(app(E1,E2),Res) :-
fv(E1,R1), fv(E2,R2),
union(R1,R2,Res).
fv(abs(V,E),Res) :-
fv(E,FV),
del(FV,V,Res).
union([],L,L) :- !.
union(L,[],L) :- !.
union([X|XS],YS,Res) :-
member(X,YS), !,
union(XS,YS,Res).
union([X|XS],YS,[X|Res]) :-
union(XS,YS,Res).
del([],_,[]).
del([X|XS],X,XS) :- !.
del([X|XS],V,[X|Res]) :-
del(XS,V,Res).
valid(Where,What,Var) :-
fv(What,FV),
chk(Where,Var,[],FV).
chk(var(V),V,BV,FV) :-
intersect(BV,FV,I), I==[].
chk(app(E1,E2),V,BV,FV) :-
chk(E1,V,BV,FV),
chk(E2,V,BV,FV).
chk(abs(V,_),V,_,_) :- !.
chk(abs(W,E),V,BV,FV) :-
chk(E,V,[W|BV],FV).
intersect([],_,[]) :- !.
intersect(_,[],[]) :- !.
intersect([X|XS],YS,[X|RS]) :-
member(X,YS),!,
intersect(XS,YS,RS).
intersect([_|XS],YS,RS) :-
intersect(XS,YS,RS).
isEta( abs( V, app(E,var(V)) ) ) :-
fv(E,FV),
not(member(V,FV)).
isEta(app(E1,E2)) :-
isEta(E1) ; isEta(E2).
isEta(abs(_,E)) :-
isEta(E).
2020/2021
Řádný termín
Magicke štvorce - NxN matica s hodnotami 1,…,N^2 hodnotami
- spraviť reprezentaciu matice NxN
cms(+N, -M)
cms(N,M)
skontroluje, že N je číslo, M je pre navrat konečnej matice Magic sqaure
cel(N,R)
vytvorí list riadku
car(N,N,M)
vytvorí výslednú maticu - list listov (list riadkov pomocou cel
)
- na poziciu X, Y v matici doplnit hodnotu V a vrátiť výslednú maticu -
set(X,Y,M,V,MM)
- doplniť zvyšnú maticu (pomocne funkcie - f. co ti da nevyuzite hodnoty, …)
solve(N,M,M) :-
getFree(M,[]),!,
chk(N,M).
solve(N,M,Res) :-
getFree(M,Free),
concat(M,L),
assertz(size_of(N)),
step(Free,[],L,[],0,ResL),
toMS(N,ResL,Res).
solve(_,_,_) :-
retractall(size_of(_)),
!,fail.
step([],[],[],Rev,_,Res) :-
reverse(Rev,Res),
size_of(N),
toMS(N,Res,M),
chk(N,M).
step(Free,[],[X|XS],Rev,Ctr,Res) :-
integer(X),
CC is Ctr+1,
try(Free,[],XS,[X|Rev],CC,Res).
step([F|FS],WasFree,[X|XS],Rev,Ctr,Res) :-
var(X),
CC is Ctr+1,
append(FS,WasFree,Xfree),
try(Xfree,[],XS,[F|Rev],CC,Res).
step([F|FS],WasFree,[X|XS],Rev,Ctr,Res) :-
var(X),
step(FS,[F|WasFree],[X|XS],Rev,Ctr,Res).
try(Xfree,[],XS,Rev,Ctr,Res) :-
size_of(N),
D is Ctr div N,
M is Ctr mod N,
D > 1,
M == 0,!,
reverse(Rev,O),
check(N,D,O),
step(Xfree,[],XS,Rev,Ctr,Res).
try(Xfree,[],XS,Rev,Ctr,Res) :-
step(Xfree,[],XS,Rev,Ctr,Res).
sumupto(N,Rest,0,Rest) :- N =< 0.
sumupto(N,[X|XS],S,Rest) :-
N > 0,
N1 is N-1,
sumupto(N1,XS,Sub,Rest),
S is X+Sub.
check(N,Rows,L) :-
Rows>1,
sumupto(N,L,Val,Rest),
RR is Rows-1,
chcl(N,RR,Val,Rest).
chcl(_,Rows,_,_) :- Rows == 0.
chcl(N,Rows,Val,L) :-
Rows > 0,
sumupto(N,L,Val,Rest),
RR is Rows-1,
chcl(N,RR,Val,Rest).
toMS(_,[],[]).
toMS(N,L,[HH|Rest]) :-
toArray(N,L,HH,TT),
toMS(N,TT,Rest).
toArray(0,L,[],L).
toArray(N,[H|T],[H|TT],Rest) :-
N > 0,
N1 is N-1,
toArray(N1,T,TT,Rest).
getFree(MS,ListN) :-
getUsed(MS,Used),
length(MS,N),
genAll(N,All),
sd(All,Used,ListN).
genAll(N,L) :-
NN is N*N,
mkl(1,NN,L).
mkl(N,M,[N|T]) :-
N < M, NN is N+1,
mkl(NN,M,T).
mkl(N,M,[M]) :-
N == M.
getUsed([],[]).
getUsed([[]|T],R) :-
getUsed(T,R).
getUsed([[H|T]|TT],R) :-
var(H),!,
getUsed([T|TT],R).
getUsed([[H|T]|TT],[H|R]) :-
getUsed([T|TT],R).
sd([],_,[]).
sd([X|XS],S,R) :-
member(X,S),!,
sd(XS,S,R).
sd([X|XS],S,[X|R]) :-
sd(XS,S,R).
concat(L1,L2) :- append(L1,L2).
chk(N,M) :-
integer(N),
N>0,
length(M,N),
maplist(length,M,LN),
all(N,LN),
append(M,AllVals),
genAll(N,AllPos),
vals(AllPos,AllVals),
csum(M).
all(_,[]).
all(N,[N|T]) :-
all(N,T).
vals([],[]).
vals(Pos,[X|XS]) :-
integer(X),
member(X,Pos),
delete(Pos,X,NewPos),
vals(NewPos,XS).
csum(M) :-
maplist(sum_list,M,[H|T]),
transp(M,MT),
maplist(sum_list,MT,TT),
all(H,T), all(H,TT),
cdiag(H,0,M),
maplist(reverse,M,MR),
cdiag(H,0,MR).
cdiag(H,S,[[V]]) :-
SS is S+V,
H == SS.
cdiag(H,S,[[V|_]|T]) :-
SS is S+V,
maplist(tail,T,TT),
cdiag(H,SS,TT).
tail([_|T],T).
head([H|_],H).
transp([],[]).
transp([[]|_],[]).
transp(XSS,[HHS|RT]) :-
maplist(head,XSS,HHS),
maplist(tail,XSS,TSS),
transp(TSS,RT).
- BONUS: definovat datovy typ obojsmerne viazany zoznam + funkciu ktora zisti dlzku zoznamu - prvky v zozname sa neopakuju
1. opravný
genV(+Start,+End, -V)
vygenerovat hodnoty od Start do End vratane (ocakavany vstup je zadany dobre); Start, End su kladné čisla
solve(+Xm, +Ym, -X, -Y, -Z)
vyriesit prehladavanim pre 1, ...Xm
a 1...Ym
rovnicu x²+y²=z²
solve(Xm,Ym,X,Y,Z) :-
genV(1,Xm,X),
genV(1,Ym,Y),
ZZ is X*X+Y*Y,
genZ(X,Y,ZZ,Z).
genZ(M1,M2,ZZ,Z) :-
max(M1,M2,S),
Zm is 2*S+1,
genV(S,Zm,Z),
Z2 is Z*Z,
Z2==ZZ.
max(X,Y,X) :- X >= Y.
max(X,Y,Y) :- X < Y.
solve(Xm, Ym, X, Y, Z) :-
genV(1, Xm, X),
genV(1, Ym, Y),
L is X * X + Y * Y,
genV(1, L, Z),
P is Z * Z,
L == P.
resolve
ako solve
ale zadava da lava a prava strana rovnice
zip(L1,L2,L12)
2. opravný termín
Definované:
/8b/ Holý prolog + not
, !
, member
, length
. Napísať predikát getAllNodes(+Num)
, ktorý do jediného parametru unifikuje počet jedinečných uzlov.
/22b/ Travelling salesman problem. Napísať predikát tsp
, ktorý nájde najlacnejšiu trasu medzi dvoma uzlami. // toto je asi zla definicia, v TSP hladame najlacnejsiu trasu z daneho uzla cez vsetky uzly naspat do daneho uzla (a kazdy uzol okrem startu navstivime 1x)
getlen(X,Y,L) :- node(X,Y,L).
getlen(X,Y,L) :- node(Y,X,L).
tsp(From,How,Price) :-
setof(J,solve(From,J),LL),
best(LL,How,Price).
best([j(H,P)],H,P) :- !.
best([j(_,P)|R],RH,RP) :-
best(R,RH,RP),
RP<P, !.
best([j(H,P)|_],H,P).
solve(From,j(How,Price)) :-
getAllNodes(LAll),
CL is LAll+1,
getlen(From,Nxt,L),
go(Nxt,From,Way,P),
Price is P+L,
How = [From|Way],
length(How,CL).
go(T,T,[T],0) :- !.
go(F,T,[F|R],PP) :-
assertz(p(F)),
getlen(F,N,P),
not(p(N)),
go(N,T,R,PR),
PP is P+PR.
go(F,_,_,_) :-
p(F),
retract(p(F)),
!, fail.
Nebo jine reseni:
tsp(From, To, HowReverse) :-
findBestPath(From, To, How),
reverse(How, HowReverse).
findBestPath(From, To, BestPath) :-
findall(Path, findPath([], [From], To, Path), AllPaths),
sort(AllPaths, [(_, BestPath) | _]).
pathCost([], 0).
pathCost([(X, Y)|RestPath], Cost) :-
node(X, Y, PathCost),
pathCost(RestPath, RestCost),
Cost is PathCost + RestCost.
findPath(Path, [To | _], To, (PathCost, Path)) :-
pathCost(Path, PathCost),
!.
findPath(Path, [LastNode | RestNodes], To, FinalPath) :-
VisitedNodes = [LastNode | RestNodes],
node(LastNode, NextNode, _),
\+ member(NextNode, VisitedNodes),
findPath([(LastNode, NextNode)|Path], [NextNode | VisitedNodes], To, FinalPath).
//Test Cases
node(a, b, 80).
node(b, c, 5).
node(c, e, 10).
node(a, d, 5).
node(d, e, 200).
:- tsp(a, e, Path)
2019/2020
Predtermin
Klika - viz popis
:- dynamic edge/2, node/2.
insUG(ug(VS,ES)) :-
inV(VS), inE(ES).
inV([]).
inV([V|VS]) :-
assertz(node(V,-1)), inV(VS).
inE([]).
inE([p(V1,V2)|ES]) :-
assertz(edge(V1,V2)), inE(ES).
isC([_]) :- !.
isC([N|NS]) :-
checkE(N,NS),isC(NS).
isC([]).
checkE(_,[]).
checkE(N,[X|XS]) :-
(edge(N,X);edge(X,N)),!,
checkE(N,XS).
deg(Node,Deg) :-
findall(N, edge(Node,N), L1),
findall(N, edge(N,Node), L2),
length(L1,N1), length(L2, N2),
Deg is N1+N2.
mkDegs :-
node(V,-1),!,
deg(V,D),
retract(node(V,-1)),
assertz(node(V,D)),
mkDegs.
mkDegs.
tryC(D,N,Nbrs, [N|Nbrs]) :-
length(Nbrs,Len),
Len == D, !,
isC([N|Nbrs]).
tryC(D,N,Nbrs, [N|L]) :-
perm(Nbrs,NX),
take(D,NX,L),
isC([N|L]).
repTry(CD,D,N,Nbrs,Clique) :-
D > CD,
tryC(D,N,Nbrs,Clique),!.
repTry(CD,D,N,Nbrs,Clique) :-
DD is D-1,
DD > CD,
repTry(CD,DD,N,Nbrs,Clique).
findC(ActD,_,ResClique) :-
node(N,D), D>ActD,
getNbr(N,AllNbrs),
fltr(D,AllNbrs,NewD,NewNbrs), NewD>ActD,
repTry(ActD,NewD,N,NewNbrs,Clique),
length(Clique,LenC),
DC is LenC - 1, DC > ActD, !,
findC(DC,Clique,ResClique).
findC(_,C,C).
getClique(ug(VS,ES),Clique) :-
retractall(node(_,_)),
retractall(edge(_,_)),
insUG(ug(VS,ES)),
mkDegs,
node(N,_),
findC(0,[N],Clique),!.
riadny
Lambda Kalkul v prologu:
fv(E,Vs) :-
fv3(E,[],Vs).
fv3(var(V),Bs,[]) :-
member(V,Bs), !.
fv3(var(V),_,[V]).
fv3(app(E1,E2),Bs,Vs) :-
fv3(E1,Bs,V1),
fv3(E2,Bs,V2),
uni(V1,V2,Vs).
fv3(abs(V,E),Bs,Vs) :-
fv3(E,[V|Bs],Vs).
uni([],L, L).
uni([X|XS],L, YS) :-
member(X,L), !,
uni(XS,L, YS).
uni([X|XS],L, [X|YS]) :-
uni(XS,L, YS).
subst(Where,What,Var,Res) :-
fv(What,FW),
sb(Where,What,FW,Var,[],Res).
sb(var(X),_,_,Var,_,var(X)) :- X \= Var, !.
sb(var(X),_,_,X,Bs,var(X)) :- member(X,Bs).
sb(var(X),What,FW,X,Bs,What) :- notIn(FW,Bs), !.
sb(app(E1,E2),What,FW,Var,Bs,app(R1,R2)) :-
sb(E1,What,FW,Var,Bs,R1),
sb(E2,What,FW,Var,Bs,R2).
sb(abs(V,E),What,FW,Var,Bs,abs(V,Res)) :-
sb(E,What,FW,Var,[V|Bs],Res).
notIn([],_) :- !.
notIn(_,[]) :- !.
notIn([X|_],YS) :-
member(X,YS),
!, fail.
notIn([_|XS],YS) :-
notIn(XS,YS).
doBR(app(abs(Var,Where),What), Res) :- subst(Where, What, Var, Res).
doBR(app(E1,E2), app(Res,E2)) :- doBR(E1,Res).
doBR(app(E1,E2), app(E1,Res)) :- doBR(E2,Res).
doBR(abs(V,E), abs(V,Res)) :- doBR(E,Res).
findR(S,S,_,[S]) :- !.
findR(_,_,N,_) :-
N > 5, !, fail.
findR(S,E,N,[S|Rest]) :-
assertz(la(S)),
doBR(S,NS),
not(la(NS)),
NN is N+1,
findR(NS,E,NN,Rest).
findR(S,_,_,_) :-
la(S),
retract(la(S)),
!, fail.
1. opravný
replaceAll(Where,What,By,Res) :-
length(Where,WL),
length(What,AL),
AL =< WL, !,
doRepl(Where,What,AL,By,Res).
replaceAll(Where,_,_,Where).
doRepl([W|WS], What, AL, By, [R1|Res]) :-
isPref(What, [W|WS]), !,
dropL(What, [W|WS], Rest),
append(By, Rest, R1),
doRepl(WS, What, AL, By, SR),
prep(W, SR, Res).
doRepl(WS, _, AL, _, []) :-
length(WS, WL),
WL < AL, !.
doRepl([W|WS], What, AL, By, Res) :-
doRepl(WS, What, AL, By, SR),
prep(W, SR, Res).
prep(X, XS, [X|XS]).
find(Lines1,SR,Lines2,Res) :-
assertz(done(Lines1,[])),
findP(Lines1,SR,Lines2,Res).
find(Lines1,_,_,_) :-
retract(done(Lines1,[])),
!,fail
findP(Lines1,_,Lines1,[]) :- !.
findP(Lines1,SR,Lines2,[T|TS]) :-
length(Lines2,LL2),
append(_,[T|_],SR),
not(done(_,T)),
T =.. [sr,What,By],
replLines(Lines1,What,By,LRep),
mkLines(LRep,LinesNew),
length(LinesNew,LN),
LN >= LL2,
not(done(LinesNew,_)),
asr_ret(LinesNew,T),
findP(LinesNew,SR,Lines2,TS).
asr_ret(L,T) :-
assertz(done(L,T)).
asr_ret(L,T) :-
retract(done(L,T)),
!,fail.
2018/2019
Řádný termín
- Napsat predikaty pro zjisteni, jestli je prvek v seznamu a pro odstraneni hodnoty ze seznamu. Dat si bacha na to, ze seznam muze obsahovat nenavazane promenne a prvek se s nima nesmi zunifikovat.
- Transpozice matice.
- Predikat, ktery bere sudoku reprezentovane matici 9x9 a vytvori seznam bloku 3x3.
- Predikat, ktery pro danou pozici v sudoku zjisti seznam moznych hodnot, ktere se na to policko daji doplnit. Mame k dispozici predikat getIth(X,M,L), ktery z matice M vytahne radek X do seznamu L. A meli jsme napsane, jak se z pozice [X,Y] v matici urci cislo bloku.
- Predikat solves, ktery s vyuzitim definovanych predikatu vyresi sudoku, ktere ma na vstupu zadane matici 9x9. Neobsazene policka jsou reprezentovana volnou promennou. Muzem pouzit getIth, getRC, ktery pro zadanou pozici a matici vrati prvek na tech souradnicich a setRC, ktery nastavi prvek v matici na nejakou hodnotu.
elemNV(X,[V|_]) :- nonvar(V), V=X, !.
elemNV(X,[_|VS]) :- elemNV(X,VS).
remVals([],_,[]).
remVals([X|XS],L,R) :- elemNV(X,L), !, remVals(XS,L,R).
remVals([X|XS],L,[X|R]) :- remVals(XS,L,R).
trp([[]|_],[]) :- !.
trp(XSS,[L|LS]) :- heads(XSS,L,YSS), trp(YSS,LS).
heads([[H|TS]|XSS],[H|T],[TS|YSS]) :- heads(XSS,T,YSS).
heads([],[],[]).
blocks([[A,B,C|CS],[D,E,F|FS],[G,H,I|IS]|XSS],[[A,B,C,D,E,F,G,H,I]|LS]) :- blocks([CS,FS,IS|XSS],LS).
blocks([[],[],[]|XSS],LS) :- blocks(XSS,LS).
blocks([],[]).
valsFor(X,Y,M,[V|VS]) :-
getIth(X,M,L),
remVals([1,2,3,4,5,6,7,8,9],L,[H|T]),
trp(M,TM),
getIth(Y,TM,R),
remVals([H|T],R,[HH|TT]),
blocks(M,BM),
P is (3*((X-1)//3)) + (1+((Y-1)//3)),
getIth(P,BM,B),
remVals([HH|TT],B,[V|VS]).
solves(M) :- search(1,1,M).
search(R,C,M) :-
getRC(R,C,M,V),
nonvar(V), !,
goNonvar(R,C,M).
search(R,C,M) :-
valsFor(R,C,M,VS),
testVals(R,C,M,VS).
goNonvar(9,9,_) :- !.
goNonvar(R,C,M) :-
newRC(R,C,RR,CC),
search(RR,CC,M).
testVals(9,9,M,[X]) :-
getRC(9,9,M,X), !.
testVals(R,C,M,[X|_]) :-
getRC(R,C,M,X),
newRC(R,C,RR,CC),
search(RR,CC,M).
testVals(R,C,M,[_|XS]) :-
testVals(R,C,M,XS).
newRC(R,C,R,CC) :-
C<9, !, CC is C+1.
newRC(R,9,RR,1) :-
R<9, RR is R+1.
getIth(1,[X|_],X) :- !.
getIth(N,[_|XS],X) :- N1 is N-1, getIth(N1,XS,X).
getRC(R,C,M,V) :-
getIth(R,M,L),
getIth(C,L,V).
1. opravny termín
Dámy
genAll(0,_,[]).
genAll(Size,Col,[pos(Col,Size)|Res]) :-
Size > 0,
SS is Size - 1,
genAll(SS,Col,Res).
inConf([pos(X,_)|_], pos(X,_)) :- !.
inConf([pos(_,Y)|_], pos(_,Y)) :- !.
inConf([pos(XX,YY)|_], pos(X,Y)) :-
tst(XX,X,YY,Y), !.
inConf([_|PS], P) :-
inConf(PS,P).
tst(XX,X,YY,Y) :-
XX<X, !, tst(X,XX,YY,Y).
tst(XX,X,YY,Y) :-
YY<Y, !, tst(XX,X,Y,YY).
tst(XX,X,YY,Y) :-
XR is XX-X,
YR is YY-Y,
XR == YR.
filterNot(_, [], []).
filterNot(Pred, [X|XS], YS) :-
call(Pred, X), !,
filterNot(Pred, XS, YS).
filterNot(Pred, [X|XS], [X|YS]) :-
filterNot(Pred, XS, YS).
tryNext(PS,Size,Possible) :-
length(PS,LPS),
NewCol is LPS+1,
genAll(Size,NewCol,NewPs),
filterNot(inConfPS),NewPs,Possible).
findQ(Size,PS,PS) :-
length(PS,Size),
!.
findQ(Size,PS,[]) :-
tryNext(PS,Size,[]),
!, fail.
findQ(Size,PS,Res) :-
tryNext(PS,Size,NewPS),
tryAll(Size,PS,NewPS,Res).
tryAll(_,_,[],_) :-
!, fail.
tryAll(Size,PS,[N|_],Res) :-
findQ(Size,[N|PS],Res).
tryAll(Size,PS,[_|NS],Res) :-
tryAll(Size,PS,NS,Res).
queens(Size,Ress) :-
setof(P,findQ(Size,[],P),Ress).
2. opravný termín
Obchodní cestující:
- Definovat predikát
search (From, To, L)
, který vyhledá nejkratší cestu z From
do To
a vrátí její délku v L
. Přičemž využívá get_distance(From,To,L)
, což je predikát pro navrácení délky cesty mezi dvěma místy.
- Definovat predikát
fsf (+From, Where, Distances)
, který vhodně navrací nejkratší vzdálenosti od From
do všech míst z množiny Where
v argumentu Distances
.
- Definovat predikát
gc (+Distances, Closest, L)
, který vybere a vrátí nejbližší bod od From
z předchozího bodu v argumentu Closest
a vzdálenost k němu v L
.
- Definovat predikát
ts (+From, +Where, -Path, -L)
, jež dostává výchozí bod a množnu dalších, které je nutné navštívit. Musí pak vybrat nejkratší cestu a vrátit ji i její délku.
2017/2018
Řádný termín
- /6b/ Flatten seznamu - vytvorit predikat e, ktery bere 2 argumenty. Prvni je seznam libovolne zanorenych seznamu (i prazdnych), napr. [[], [1, 2], [[[[]]],[atom, atom]]]. Druhy argument je vysledny seznam bez zanoreni.
- /7b/ Funkce XOR, ktera vraci symterickou diferenci dvou mnozin (sjednoceni mnozin bez jejich pruseciku). Bere prvni a druhy parametr mnozinu reprezentovanou seznamem, treti parametr je vysledna mnozina reprezentovana seznamem.
- /9b/ Napisat predikat search(PocatecniPozice, SeznamCest), ktory najde vsechny cesty z dane pozice zpet do teto pozice, delky 20 az 22 kroku (netrapit se tim, jestli vracet prvni/posledni prvek ci ne). Kazdy prvok je mozne nastivit len jeden krat vyjma prveho (== posledneho). Definicia pozicie je neznama, napiste funkci nextStep(Pos, NewPos) nad neznamym a NEKONECNYM stavovym priestorom. Mozno pouzit retract*, assert*, bagof, setof, length.
- /8b/ Napisat predikat lookup. Prvy arguement vhodne reprezentovana tabulka symbolov, 2-hy argument kluc, 3-ty argument hodnota. A posledny a vysledny argument je modifikovana, pripadne vstupna tabulka symbolov.
Predikat pracuje v dvoch rezimoch. Ak je zadana hodnota, tak sa modifikuje pripadne modifikuje zaznam (klic -> hodnota?) v tabulke symbolov. Ak nie je zadana hodnota, tak vyhladavame v tabulku hodnotu so zadanym klucom. Ak sa nemylim, tak bolo mozne pouzit vsetko zo zakladnej kniznice Prologu. Ja som pouzil var(), nonvar() na zistenie, ci (nie) je zadana hodnota a nemyslim si, ze by to bolo v zadani spomenute. – priklad byl mozna lehce modifikovany?
:- dynamic
pos/1.
e([],[]).
e([[]|R],Res) :- !, e(R,Res).
e([[X|XS]|YS],Res) :- !, e([X,XS|YS],Res).
e([V|XS],[V|Res]) :- e(XS,Res).
xor([],L,L) :- !.
xor(L,[],L) :- !.
xor(L,R,Res) :- sub(L,R,L1),sub(R,L,R1),app(L1,R1,Res).
sub([],_,[]).
sub([X|XS],YS,RS) :- elem(X,YS),!,sub(XS,YS,RS).
sub([X|XS],YS,[X|RS]) :- sub(XS,YS,RS).
elem(X,[X|_]) :- !.
elem(X,[_|XS]) :- elem(X,XS).
app([],L,L).
app([X|XS],L,[X|RS]) :- app(XS,L,RS).
search(P,Res) :-
setof(Path,s(P,P,0,Path),Res).
s(P,P,N,[P]) :- N =< 22, N >= 20, !.
s(_,_,N,_) :- N > 22, !, fail.
s(P,P,N,_) :- N \= 0, !, fail.
s(A,P,N,[A|R]) :-
assertz(pos(A)),
NN is N+1,
nextStep(A,AA),
( not(pos(AA)) ; AA=P ) ,
s(AA,P,NN,R).
s(A,_,_,_) :-
pos(A),
retract(pos(A)),
!,fail.
nextStep(p(X,Y),p(XX,Y)) :- XX is X+1.
nextStep(p(X,Y),p(XX,Y)) :- XX is X-1.
nextStep(p(X,Y),p(X,YY)) :- YY is Y+1.
nextStep(p(X,Y),p(X,YY)) :- YY is Y-1.
emptyT([]).
lookup(T,_,_,_) :- var(T), !, fail.
lookup(T,Var,Val,NT) :- nonvar(Var),nonvar(Val), !, iT(T,Var,Val,NT).
lookup(T,Var,Val,T) :- nonvar(Var), lT(T,Var,Val).
iT([], R, L, [p(R,L)]).
iT([p(R,_)|PS], R, L, [p(R,L)|PS]) :- !.
iT([p(RR,LL)|PS], R, L, [p(RR,LL)|PPS]) :- iT(PS,R,L,PPS).
lT([p(R,L)|_],R,L) :- !.
lT([_|PS],R,L) :- lT(PS,R,L).
1. opravny termín
- Holý Prolog. Napsat predikát
mkTrans(ListOfLists,ListOfLists)
, která dostane v 1. argumentu matici, kterou transponovanou unifikuje do 2. argumentu.
- Holý Prolog. Napsat predikát
subseq
, který v 1. argumentu dostane seznam a do 2. argumentu unifikuje seznam všech jeho podseznamů, tedy jde tam o prefix a suffix matching.
- Prolog s
bagof, setof, assert, retract
atp. Prohledávání stavového prostoru. Napsat predikát search(Start,Cíl, Nejkratší_cesta)
, který dostane nějakou startovní a koncovou pozici a unifikuje do 3. argumentu nejkratší cestu mezi nimi. Napsat také predikát nextStep
, který bude vracet další novou pozici. úkolem není napsat optimální řešení, ale využít elegantnosti Prologu.
search(S,E,Res) :-
retractall(pos(_)),
steptry(S,E,0,Res).
steptry(S,E,N,Res) :-
s(S,E,N,Res), !.
steptry(S,E,N,Res) :-
NN is N+1,
steptry(S,E,NN,Res).
s(E,E,0,[E]) :- !.
s(_,_,N,_) :- N < 0, !, fail.
s(A,E,N,[A|R]) :-
assertz(pos(A)),
NN is N-1,
nextStep(A,AA),
not(pos(AA)) ,
s(AA,E,NN,R).
s(A,_,_,_) :-
pos(A),
retract(pos(A)),
!,fail.
nextStep(p(X,Y),p(XX,Y)) :- XX is X+1.
nextStep(p(X,Y),p(XX,Y)) :- XX is X-1.
nextStep(p(X,Y),p(X,YY)) :- YY is Y+1.
nextStep(p(X,Y),p(X,YY)) :- YY is Y-1.
- Prolog s celočíselným dělením, dělením a is. Napsat Prologovou reprezentaci racionálních čísel a operaci násobení a sčítání nad nimi.
gcd(N,N,N) :- !.
gcd(N,M,M) :-
N > M,
NN is mod(N,M),
NN==0, !.
gcd(N,M,D) :-
N > M, !,
NN is mod(N,M),
gcd(M,NN,D).
gcd(N,M,N) :-
M > N,
MM is mod(M,N),
MM is 0, !.
gcd(N,M,D) :-
MM is mod(M,N),
gcd(N,MM,D).
ev(op('+',L,R),rac(NN,DD)) :-
ev(L,rac(LN,LD)),
ev(R,rac(RN,RD)),
N1 is LN*RD + RN*LD,
D1 is LD*RD,
norm(N1,D1,NN,DD).
ev(op('*',L,R),rac(NN,DD)) :-
ev(L,rac(LN,LD)),
ev(R,rac(RN,RD)),
N1 is LN*RN,
D1 is LD*RD,
norm(N1,D1,NN,DD).
ev(rac(X,Y),rac(X,Y)).
norm(N,D,NN,DD) :-
gcd(N,D,G), G>1,!,
NN is div(N,G),
DD is div(D,G).
norm(N,D,N,D).
2016/2017
Riadny termín
- Prohledávání stavového prostoru. Napsat predikát getPath, který má jako první parametr startovní bod a jako druhý cílový bod a do třetího unifikuje nejkratší (s nejmenší cenou) cestu mezi těmito body. Předpokládejte, že stavový prostor je konečný. Máte k dispozici predikát nextStep(X, XX, P), který jako první parametr dostane nějaký stav stavového prostoru a v druhém vrátí další stav a ve třetím bude výsledná cena tohoto kroku. (14b)
nextStep('a', 'b', 3). nextStep('a', 'c', 2). nextStep('a', 'f', 5).
nextStep('b', 'a', 3). nextStep('b', 'c', 1). nextStep('b', 'd', 6).
nextStep('c', 'a', 2). nextStep('c', 'b', 1). nextStep('c', 'd', 4). nextStep('c', 'e', 4).
nextStep('d', 'b', 6). nextStep('d', 'c', 4). nextStep('d', 'e', 3).
nextStep('e', 'c', 4). nextStep('e', 'd', 3). nextStep('e', 'f', 2).
nextStep('f', 'a', 5). nextStep('f', 'e', 2).
:- dynamic
visited/1,
best_price/1,
best_path/1.
getPath(S,E,Path) :-
retractall(visited(_)),
retractall(best_price(_)),
retractall(best_path(_)),
assert(best_price(none)),
getPathHelper(S,E,Path).
getPathHelper(S,E,_) :- search(S,E,0,[]).
getPathHelper(S,_,[S|Path]) :- best_path(Path).
search(E,E,Price,Path) :- checkP(Price, Path), fail.
search(S,E,P,TP) :-
assertz(visited(S)),
nextStep(S,Nxt,SP),
not(visited(Nxt)),
NP is P+SP,
append(TP,[Nxt],NTP),
search(Nxt,E,NP,NTP).
search(S,_,_,_) :-
retract(visited(S)),
!, fail.
checkP(NP,Path) :-
best_price(none),
retract(best_price(none)),
assert(best_price(NP)),
assert(best_path(Path)).
checkP(NP,Path) :-
best_price(P),
NP<P,
retract(best_price(P)),
retract(best_path(_)),
assert(best_price(NP)),
assert(best_path(Path)).
- Holý prolog (unifikace, základní práce se seznamy, + řez tuším). Navrhnout strukturu pro ukládání boolovských výrazů (pro and, or, not) nad proměnnými a literály true/false. Dále strukturu pro ukládání hodnot proměnných. Dále napsat predikát eval(Table, Expr, Res), která vyhodnotí daný bool výraz. V table je tabulka hodnot proměnných. Expr je vyhodnocovaný výraz. Do Res se unifikuje výsledek. (6b)
eval(_,true,true).
eval(_,false,false).
eval(T,var(V),R) :- getVal(T,V,R), !.
eval(T,not(E),R) :-
eval(T,E,EvalE1),
(EvalE1, eval(_, false, R); eval(_, true, R)), !.
eval(T,and(E1,E2),R) :-
eval(T,E1,EvalE1),
(EvalE1, eval(T,E2,R); eval(_,false,R)), !.
eval(T,or(E1,E2),R) :-
eval(T,E1,EvalE1),
(EvalE1, eval(_,true,R); eval(T,E2,R)), !.
getVal([(V,Value)|_],V,Value).
getVal([_|WS],V,Value) :- getVal(WS,V,Value).
- Holý prolog (unifikace, základní práce se seznamy). Implementujte predikát msort, který provádí merge sort řazení seznamu hodnot. Musí to být merge sort s jeho klasickou složitostí (ne kvadratickou…). (7b)
- Cely prolog, ale nesmi se pouzit vestaveny append a jeste 2 veci co si nepamatuju. Mame predikat, kde prvni parametr je predikat (dvouparametrovy - tedy jeden vstup a výsledek) a druhy je seznam seznamu. Z druheho parametru se postupně berou seznamy a ma se provest aplikace predikatu na vsechny hodnoty v seznamu a dat dohromady vysledky do jednoducheho seznamu (tedy ne seznam seznamu). (6b)
Lambda kalkul
Pevny bod
- prezentacia lambda calcul 30-33 slide
- pomocka aby si mohol duplikovat/replikovat/rekurzivne pracovat s funkciou
- napr. klasicky mas sucet 2 cisel, ale s vyuzitim pevneho bodu mozes scitat hocikolko cisel
cize mozes spravit SUM 1 2 3 4 5 6 7 8 9
miesto len SUM 1 2

Cheatsheet

2021/2022
termin
- operátor pevného bodu pro LT
k dispozici je: iszero, prev, reprezentace celých čísel (prev 0 = 0), zbytek si musíme navrhnout sami (ternární operátor třeba k dispozici nebyl)
1. opravný
- POW x n - x ^ n, zadané True, dolplniť false, ternarny operator a
2020/2021
riadny
definovať xor, true false podla seba
2. opravný termín
/2b/ Napísať výraz, kde 2 premenné sú volné a zároveň aj viazané
- vrámci jedného výrazu (NIE 2 rôznych výrazov).
/4b/ Napísať príklad pre platnú a neplatnú substitúciu
- vrámci jedného výrazu (NIE 2 rôznych výrazov).
2019/2020
předtermín
Bylo definovaný True
jako \xy.xy
.
Muselo se definovat False
libovolným způsobem.
Dál bylo potřeba definovat ternární operátor ? :
.
A v poslední řadě definovat funkci eq
, která porovnává dvě celá čísla. U toho bylo možné využít funkce iszero
a prev
. Tohle bylo potřeba implementovat pomocí operátoru pevného bodu.
2018/2019
LT bude asi funkcia less <
2017/2018
/6b/ Op. pevneho bodu - MINUS x y. Nadefinovat True + False. K dispozici isZero, prev. Pripadne si dodefinovat dalsi funkce.
2016/2017
Ukázat vlastnost operátoru pevného bodu. V lamda kalkulu definovat násobení (MUL) s dvěma parametry pomocí prev, add, iszero a ternárního operátoru (6b)
2015/2016
Popsat operátor pevného bodu, jeho vlastnost.
Pomocí něj a předdefinovaných funkcí isZero, add a ternárního operátoru vytvořit výraz SUM (funkce fungují tak jak čekáme, ale mají nám neznámou implementaci, taky čísla mají neznámou implementaci).
Výraz SUM vezme dvě čísla, x a y, a pokud je y=0, vrátí x, jinak vrátí SUM (x+y) (tedy částečně aplikovaného sama sebe).
Ukázat vyhodnocení SUM 2 3 0.
1. opravný
Mějme definováno True jako: True = \ x y . x y
.
Definujte False standardního významu dle libosti. S jejích pomoci definujte IMP (implikace zleva doprava) standardního významu.
Redukujte po krocíchIMP True False = False
2014/2015
Řádny
Definicia vlastnosti operatoru pevneho bodu.
Potom pomocou tohoto operatoru, iszero a prev nadefinovat minus, ktore berie 2 cisla a odcita ich a - b, pricom vysledok je nezaporny (tj. ==0 ak je b vacsie ako a).
Mali sme zohladnit, ze iszero, prev a cisla maju neznamu definiciu, ale znamy vyznam. True a False je mozne si nadefinovat podla seba.
1. opravný
2013/2014
pevny bod, nadefinovat GE
Důkazy
Návod
Ne všechno je definované v zadání. Například foldr, foldl a podobné definice je potřeba znát z paměti.
Pamatať si:
je treba dokazať L=P pre
- ak je v zadaní len xs:
· xs = []
· xs = (a:as)
- ak je v zadaní xs aj ys:
· xs = [] (ľubovolné ys - pozn. zostáva také isté)
· ys = [] (ľubovolné xs - pozn. zostáva také isté)
· xs = (a:as), ys = (b:bs)
I.P./I.H. je same shit indukčný predpoklad/hypotéza (je to v podstate odpisane len dokazovane zadanie)
2022/2023
Předtermín
V haskellu je dano
- suma a [] = a
- suma a (x:xs) = suma (a + x) xs
Dokazte, ze `suma 0 xs = foldl (+) 0 xs`. Byla tam poznamka, ze mame vhodne zvolit indukcni hypotezu (8b)
Pozor na foldl a ne foldr
2021/2022
termin
- concat = foldr (:) pro konečné xs a ys
concat xs ++ ys = foldr (:) ys xs

1. opravný
(14b alebo 16b)
Axiomy:
Dokazujeme pomocí strukturální indukce s indukční proměnnou xs:
map (uncurry f) (zip xs ys) = zipWith f xs ys
2020/2021
riadny
Zadanie: all xs = foldr (&&) True xs
Dôkaz:
2. opravný termín
Zadané:
Dodefinujte funkciu f
tak, aby platilo zp f xs ys = df xs ys
a dokážte to pre všetky konečné xs
a ys
.
2019/2020
předtermín
Dokázat, že concat xs = foldr (++) [] xs
, když:
Definiční rovnice pro foldr bylo potřeba si nadefinovat.
riadny
Pre len xs = foldr (\_ n-> 1+n) 0 xs
Postup:
1. opravny
Pre map (+1) xs = inc xs
Postup:
2018/2019
riadny
Dokážte, že platí any xs = foldr (||) False xs
když:
1. opravny
Dokážte, že platí [] ++ as = as ++ [] = as
když:
Postup:
2017/2018
Radny
Opravny
2016/2017
staršie
Zadanie: take n as ++ drop n as = as
riešenie:
-
Zadanie len(xs ++ ys) = len xs + len ys
fituska link

-
Zadanie map f (xs ++ ys) = map f xs ++ map f ys
fituska link
-
Zadanie rev xs = reverse xs
- Zadanie
foldr (++) [] xs = ccat xs
-
Zadanie map f (xs ++ ys) = (map f xs) ++ (map f ys)

-
Zadanie sum (xs ++ ys) == sum xs + sum ys
- Zadanie
length (xs ++ ys) == length xs + length ys
Dokazujeme pomocí strukturální indukce nad proměnnou xs.
První krok: xs = []
Druhý krok: xs = (a:as)
Indukční předpoklad: length (as ++ ys) == length as + length ys
Dokazujeme: length ((a:as) ++ ys) == length (a:as) + length ys
V jazyku Haskell, necht je operátor
Ukažte, že xs ++ ys = foldr (:) ys xs
pro danou definici ++ a všechna konečná xs a ys.
Axiomy:
Postup: