Tomáš Křen (tomkren na džímejlu kom)
Pá od 10:40 v S1
import Data.List data Paska s = Paska [s] s [s] class (Show s) => Sym s where empty :: s showSyms :: [s] -> String showSyms = concat . map show instance Sym Char where empty = ' ' instance Sym Int where empty = 0 showSyms = concat . intersperse "," . map show mkPaska :: (Sym s) => [s] -> Paska s mkPaska [] = Paska [] empty [] mkPaska (x:xs) = Paska [] x xs instance (Sym s) => Show (Paska s) where show (Paska xs s ys) = (showSyms . reverse $ xs) ++ "["++(show s)++"]" ++ (showSyms ys) moveHeadLeft :: (Sym s) => Paska s -> Paska s moveHeadLeft (Paska [] s ys) = Paska [] empty (s:ys) moveHeadLeft (Paska (x:xs) s ys) = Paska xs x (s:ys) moveHeadRight :: (Sym s) => Paska s -> Paska s moveHeadRight (Paska xs s []) = Paska (s:xs) empty [] moveHeadRight (Paska xs s (y:ys)) = Paska (s:xs) y ys data Move = L | N | R deriving (Show) moveHead :: (Sym s) => Move -> Paska s -> Paska s moveHead move = case move of L -> moveHeadLeft N -> id R -> moveHeadRight type StepFun q s = (q,s) -> Maybe (q,s,Move) data TM q s = TM { stepFun :: StepFun q s, initState :: q, finStates :: [q] } data TMConfig q s = TMConfig q (Paska s) class (Show q, Eq q) => State q where instance (State q, Sym s) => Show (TMConfig q s) where show (TMConfig q paska) = "<"++(show q)++"> "++(show paska) data StepResult q s = Next (TMConfig q s) | Halt (TMConfig q s) | Fail tmStep :: (State q, Sym s) => TM q s -> TMConfig q s -> StepResult q s tmStep tm (TMConfig q (Paska xs s ys)) = case stepFun tm (q,s) of Nothing -> Fail Just (q',s',move) -> let paska' = moveHead move (Paska xs s' ys) resultCons = if q' `elem` finStates tm then Halt else Next in resultCons $ TMConfig q' paska' tmRun :: (State q, Sym s) => TM q s -> [s] -> IO () tmRun tm input = run $ TMConfig (initState tm) (mkPaska input) where putConfig = putStrLn . show run config = do putConfig config case tmStep tm config of Next config' -> run config' Halt config' -> putConfig config' Fail -> return () -- Busy Beaver : https://en.wikipedia.org/wiki/Busy_beaver instance State Int where bb3 :: StepFun Int Char bb3 x = case x of (1,' ') -> Just (2,'*',R) (1,'*') -> Just (3,'*',L) (2,' ') -> Just (1,'*',L) (2,'*') -> Just (2,'*',R) (3,' ') -> Just (2,'*',L) (3,'*') -> Just (4,'*',R) tmBB3 :: TM Int Char tmBB3 = TM { initState = 1, finStates = [4], stepFun = bb3 }
cv12.hs :
{-# LANGUAGE FlexibleInstances #-} import Text.JSON import WebServer data Tree a = Tree a [Tree a] treeFold :: (a -> [acc] -> acc) -> Tree a -> acc treeFold f (Tree x ts) = f x $ map (treeFold f) ts data Expr op val = Expr op (Expr op val) (Expr op val) | Val val deriving (Show,Read) exprFold :: (op->acc->acc->acc) -> (val->acc) -> Expr op val -> acc exprFold fNode fLeaf = g where g (Val x) = fLeaf x g (Expr op e1 e2) = fNode op (g e1) (g e2) -- exprFold' :: ((a->a->a) -> (acc->acc->acc)) evalExpr :: (Expr (a->a->a) a) -> a evalExpr = exprFold id id e1 = Val 1 e2 = Expr (+) (Val 2) (Val 4) type Dic val = String -> val -> val -> val dic1 "+" = (+) dic1 "-" = (-) dic1 "*" = (*) dic1 "/" = (/) evalExprDic :: Dic val -> (Expr String val) -> val evalExprDic dic = exprFold dic id e3 = Val 1 e4 = Expr "+" (Val 2) (Val 4) e5 = Expr "*" (Val 7.0) (Expr "+" (Val 2.0) (Val 4.0)) -- showJSON :: JSON a => a -> JSValue -- readJSON :: JSON a => JSValue -> Result a instance JSON (Expr String Double) where showJSON e = case e of Val x -> showJSON x Expr op e1 e2 -> showJSON $ [showJSON op, showJSON e1, showJSON e2] readJSON jsVal = case jsVal of JSArray [jsOp,jsE1,jsE2] -> do op <- readJSON jsOp e1 <- readJSON jsE1 e2 <- readJSON jsE2 Ok $ Expr op e1 e2 JSRational _ x -> Ok . Val . fromRational $ x _ -> Error "Unsupported format." evalExprJson :: Dic Double -> String -> Result Double evalExprJson dic jsonStr = case decode jsonStr of Ok expr -> Ok $ evalExprDic dic expr Error msg -> Error msg runEvalServer :: IO () runEvalServer = runWebServer 80 evalServerFun evalServerFun :: String -> String evalServerFun reqStr = case evalExprJson dic1 reqStr of Ok x -> show x Error msg -> msg
WebServer.hs :
{-# LANGUAGE OverloadedStrings #-} module WebServer (runWebServer) where -- https://hackage.haskell.org/package/wai import Network.Wai (Application, Response, responseLBS, rawPathInfo) import Network.Wai.Handler.Warp (run) import Network.HTTP.Types (status200) import Network.HTTP.Base (urlDecode) import qualified Data.ByteString.Lazy as BsLazy import qualified Data.ByteString.UTF8 as BsUTF import qualified Data.Text as T import qualified Data.Text.Encoding as E type Port = Int -- example ----------------------------------------------------------- exampleServerFun :: String -> String exampleServerFun cmd = "{\"cmd\":\""++ cmd ++"\"}" runExample :: IO () runExample = runWebServer 8080 exampleServerFun -- exported functions ------------------------------------------------ runWebServer :: Port -> (String -> String) -> IO () runWebServer port serverFun = do putStrLn $ "Server running at http://localhost:" ++ show port ++ "/" run port $ mkApp serverFun ------------------------------------------------------------------------ mkApp :: (String -> String) -> Application mkApp serverFun request respond = respond . jsonResponse . serverFun . processPath . rawPathInfo $ request jsonResponse :: String -> Response jsonResponse jsonStr = responseLBS status200 jsonContentType $ str2lazy jsonStr where jsonContentType = [("Content-Type", "application/json; charset=utf-8")] processPath :: BsUTF.ByteString -> String processPath = urlDecode . T.unpack . trimSlashes . E.decodeUtf8 str2lazy :: String -> BsLazy.ByteString str2lazy = BsLazy.fromStrict . BsUTF.fromString trimSlashes :: T.Text -> T.Text trimSlashes = T.dropWhile isSlash . T.dropWhileEnd isSlash where isSlash = (=='/')
data Mozna a = Nic | Proste a deriving (Show) instance Functor Mozna where fmap f mx = case mx of Nic -> Nic Proste x -> Proste (f x) instance Applicative Mozna where pure = Proste mf <*> mx = case mf of Nic -> Nic Proste f -> fmap f mx instance Monad Mozna where mx >>= f = case mx of Nic -> Nic Proste x -> f x safeLog :: Double -> Mozna Double safeLog x | x <= 0 = Nic | otherwise = Proste (log x) safeSqrt :: Double -> Mozna Double safeSqrt x | x < 0 = Nic | otherwise = Proste (sqrt x) mSafeLog :: Double -> Maybe Double mSafeLog x | x <= 0 = Nothing | otherwise = Just (log x) mSafeSqrt :: Double -> Maybe Double mSafeSqrt x | x < 0 = Nothing | otherwise = Just (sqrt x) safeSqrtLog :: Double -> Mozna Double safeSqrtLog x = case safeLog x of Nic -> Nic Proste y -> safeSqrt y najdi :: Eq a => [a] -> a -> Mozna Int najdi xs y = f xs 0 where f [] _ = Nic f (x:xs) n | x == y = Proste n | otherwise = f xs (n+1) safeHead :: [a] -> Mozna a safeHead [] = Nic safeHead (x:_) = Proste x najdiPrvni :: Eq a => [a] -> [a] -> Mozna Int najdiPrvni xs ys = case safeHead ys of Nic -> Nic Proste y -> najdi xs y lbind :: (a -> Mozna b) -> Mozna a -> Mozna b lbind f mx = case mx of Nic -> Nic Proste x -> f x rbind :: Mozna a -> (a -> Mozna b) -> Mozna b rbind = flip lbind bSafeSqrtLog :: Double -> Mozna Double bSafeSqrtLog x = lbind safeSqrt (safeLog x) bNajdiPrvni :: Eq a => [a] -> [a] -> Mozna Int bNajdiPrvni xs ys = lbind (najdi xs) (safeHead ys) rSafeSqrtLog :: Double -> Maybe Double rSafeSqrtLog x = (mSafeLog x) >>= mSafeSqrt doSafeSqrtLog :: Double -> Maybe Double doSafeSqrtLog x = do y <- mSafeLog x mSafeSqrt y -- mSafeLog x >>= (\y -> mSafeSqrt y) -- PISKVORKY ------------------------------- startDeska = "....x...." showDeska :: [Char] -> String showDeska xs = "\n" ++ take 3 xs ++ "\n" ++ take 3 (drop 3 xs) ++ "\n" ++ take 3 (drop 6 xs) ++ "\n" dalsiDesky :: Char -> [Char] -> [[Char]] dalsiDesky hrac deska = f ([],deska) where f (_,[]) = [] f (xs,y:ys) | y == '.' = (xs++(hrac:ys)) : f (xs++[y], ys) | otherwise = f (xs++[y], ys) showDesky :: [[Char]] -> String showDesky = concat . map showDeska putDesky :: [[Char]] -> IO () putDesky = putStrLn . showDesky poJednom :: [[Char]] poJednom = dalsiDesky 'o' startDeska poDvouTazich :: [[Char]] poDvouTazich = concat $ map (dalsiDesky 'x') (dalsiDesky 'o' startDeska) bPoDvouTazich = [startDeska] >>= dalsiDesky 'o' >>= dalsiDesky 'x' doPoDvouTazich = do a <- [startDeska] b <- dalsiDesky 'o' dalsiDesky 'x' -- Dů: verze1 = [ (x,y) | x <- xs , y <- ys , x + y > 10 ] {- Udělejte funkci sraz, aby fungovalo verze2 = do x <- xs y <- ys straz (x + y > 10) return (x,y) -}
-- Dů (1) : isInside :: Tvar -> Bod -> Bool type Bod = (Double,Double) type Polomer = Double data Tvar = Obdelnik Bod Bod | Kruh Bod Polomer | Trojuhelnik Bod Bod Bod -- (2) Pro tento typ stromu udělejte fold data Tree a = Tree a [Tree a] -- (3) Definujte datový typ pro herní karty -- (4*) Navrhněte datovou strukturu pro aritm výraz -- a udělejte vyhodnocení pomocí foldu. -------------------------- mensiNez n xs = [ 2*x | x <- xs , x < n] mensiNez2 n = map (2*) . filter (t -> [t] -> [t] -> [(t, t)] allPairsVeciNez n xs ys = [(x,y) | x <- xs, y <-ys, x+y > n] delitele :: Integer -> [Integer] delitele n = [ x | x <- [1..n] , n `mod` x == 0] cislaADelitele = [ (n, delitele n) | n <- [1..] ] ----------------------------------------------- -- data Bool = False | True data Barva = Cervena | Zelena | Modra | Cerna | Bila --deriving --(Show,Eq,Ord,Enum,Read) instance Show Barva where show b = case b of Cervena -> "C" Zelena -> "Z" Modra -> "M" Cerna -> "Cerna" Bila -> "B" barvaNaRGB :: Barva -> (Int,Int,Int) barvaNaRGB b = case b of Cervena -> (255,0,0) Zelena -> (0,255,0) Modra -> (0,0,255) Cerna -> (0,0,0) Bila -> (255,255,255) data BarvaRGB = CervenaRGB | ZelenaRGB | ModraRGB | CernaRGB | BilaRGB | RGB Int Int Int data Dvojice a = D a a deriving (Show) data Pair a b = Pair a b prvni :: Pair a b -> a prvni (Pair x _) = x druhy :: Pair a b -> b druhy (Pair _ x) = x naTuple :: Pair a b -> (a,b) naTuple (Pair x y) = (x,y) --- data Strom a = Uzel (Strom a) a (Strom a) | Nil pridej :: (Ord a) => Strom a -> a -> Strom a pridej Nil x = Uzel Nil x Nil pridej (Uzel t1 val t2) x | x < val = Uzel (pridej t1 x) val t2 | otherwise = Uzel t1 val (pridej t2 x) list2bst :: (Ord a) => [a] -> Strom a list2bst xs = foldl pridej Nil xs showStrom :: (Show a) => Strom a -> [String] showStrom Nil = [] showStrom (Uzel t1 val t2) = let odsad str = " " ++ str radkyUzlu = (showStrom t2) ++ [show val] ++ (showStrom t1) in map odsad radkyUzlu instance Show a => Show (Strom a) where show tree = unlines $ showStrom tree data List a = Cons a (List a) | Empty myFoldr :: (a -> b -> b) -> b -> (List a -> b) myFoldr fCons vEmpty Empty = vEmpty myFoldr fCons vEmpty (Cons x xs) = fCons x (myFoldr fCons vEmpty xs) myFoldr2 :: (a -> b -> b) -> b -> (List a -> b) myFoldr2 fCons vEmpty = g where g Empty = vEmpty g (Cons x xs) = fCons x (g xs) stromFold :: (b -> a -> b -> b) -> b -> Strom a -> b stromFold fUzel vNil Nil = vNil stromFold fUzel vNil (Uzel t1 val t2) = fUzel (stromFold fUzel vNil t1) val (stromFold fUzel vNil t2) stromFold2 :: (b -> a -> b -> b) -> b -> Strom a -> b stromFold2 fUzel vNil = g where g Nil = vNil g (Uzel t1 val t2) = fUzel (g t1) val (g t2) bst2list :: Strom a -> [a] bst2list tree = stromFold (\ xs val ys -> xs ++ [val] ++ ys) [] tree
import Data.List import Data.Char split :: (a -> Bool) -> [a] -> ([a],[a]) split p xs = foldr f ([],[]) xs where f x (xs,ys) | p x = (x:xs,ys) | otherwise = (xs,x:ys) split2 :: (a -> Bool) -> [a] -> ([a],[a]) split2 p = foldr (\ x (xs,ys) -> if p x then (x:xs,ys) else (xs,x:ys)) ([],[]) curry' :: ((a,b) -> c) -> (a -> (b -> c)) --curry f = \ x -> (\ y -> f (x,y)) curry' f x y = f (x,y) -- \ x y z -> ... -- \ x -> (\ y -> ( \ z -> ... )) uncurry' :: (a -> b -> c) -> (a,b) -> c uncurry' f (x,y) = f x y flip' :: (a -> b -> c) -> b -> a -> c flip' f y x = f x y -- zretez seznamy (+++) :: [a] -> [a] -> [a] (+++) xs ys = foldr (:) ys xs concat' :: [[a]] -> [a] concat' = foldr (+++) [] sum' :: Num a => [a] -> a sum' = foldl (+) 0 prod' :: Num a => [a] -> a prod' = foldl (*) 1 len :: [a] -> Int len = foldr (\_->(+1)) 0 map' :: (a -> b) -> [a] -> [b] map' f = foldr (\ x-> ((f x) :)) [] filter' :: (a -> Bool) -> [a] -> [a] filter' p xs = foldr (\ x acc -> if p x then x:acc else acc) [] xs horner :: Num a => [a] -> a horner xs = foldl (\acc x-> acc * 10 + x) 0 xs readCifra :: Char -> Int readCifra ch = ord ch - ord '0' -- ($) :: (a -> b) -> a -> b -- f $ x = f x -- (.) :: (b->c) -> (a->b) -> (a->c) -- (g . f) x = g (f x) readInt :: [Char] -> Int readInt str = horner ( map readCifra str ) readInt' :: String -> Int readInt' str = foldl (\acc x-> acc * 10 + x) 0 $ map readCifra str readInt'' :: String -> Int readInt'' = (foldl (\acc x-> acc * 10 + x) 0) . (map readCifra) readInt''' :: String -> Int readInt''' = foldl ((+).(*10)) 0 . map (((-)(ord '0')).ord) ss :: Num a => [a] -> [a] -> a ss x = sum . (zipWith (*) x) -- boobs operator (.).(.) -- proč nefunguje? -- ss' = sum ((.).(.)) (zipWith (*)) my_foldl f a bs = (foldr (\ b g -> (\x -> g (f x b) )) id bs) a
Domácí úkol: Napište ekvivalent funkce filter, která (místo toho, aby vracela seznam elementů, které splní podmínku) vrací dvojici seznamů: První s elementy, které podmínku splňují; druhý s elementy, které podmínku nesplňují. Implementujte funkci tak, aby prošla seznam jen jednou (tzn ne "dvakrát filter").
fac :: Integer -> Integer fac n | n < 0 = error "To nechces!" | n == 0 = 1 | otherwise = n * fac (n-1) fac2 n = if n == 0 then 1 else n * fac2 (n-1) my_map :: (a -> b) -> [a] -> [b] my_map _ [] = [] my_map f (x:xs) = (f x) : (my_map f xs) my_take :: Int -> [a] -> [a] my_take 0 _ = [] my_take _ [] = [] my_take n (x:xs) | n < 0 = error "n musí byt nezaporny" | otherwise = x : (my_take (n-1) xs) my_takeWhile :: (a -> Bool) -> [a] -> [a] my_takeWhile _ [] = [] my_takeWhile f (x:xs) | f x = x : (my_takeWhile f xs) | otherwise = [] seznamDruhychMocnin = map (2^) [1..] my_zip :: [a] -> [b] -> [(a,b)] my_zip [] _ = [] my_zip _ [] = [] my_zip (x:xs) (y:ys) = (x,y) : (my_zip xs ys) my_zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] my_zipWith _ [] _ = [] my_zipWith _ _ [] = [] my_zipWith f (x:xs) (y:ys) = (f x y) : (my_zipWith f xs ys) -- 0 [1,2,3,4,5] -- (((((0 + 1) + 2) + 3) + 4) + 5) my_foldl :: (a -> b -> a) -> a -> [b] -> a my_foldl _ acc [] = acc my_foldl f acc (x:xs) = my_foldl f (f acc x) xs -- [1,2,3,4,5] 0 -- 1 + (2 + (3 + (4 + (5 + 0)))) my_foldr :: (b -> a -> a) -> a -> [b] -> a my_foldr _ z [] = z my_foldr f z (x:xs) = f x (my_foldr f z xs) my_foldl1 :: (a->a->a) -> [a] -> a my_foldl1 f (x:xs) = my_foldl f x xs skals :: Num a => [a] -> [a] -> a skals x y = my_foldl1 (+) (my_zipWith (*) x y) suma :: Num a => [a] -> a --sum xs = my_foldl1 (+) xs suma = my_foldl1 (+) my_filter :: (a -> Bool) -> [a] -> [a] my_filter _ [] = [] my_filter p (x:xs) | p x = x : (my_filter p xs) | otherwise = my_filter p xs
% ulice(dum(barva,skola,jazyk,firma,zvire),...) uliceMaDum(ulice(D1,D2,D3,D4,D5),D) :- D=D1; D=D2; D=D3; D=D4; D=D5. napravo(ulice(D1,D2,D3,D4,D5),Da,Db) :- (Db=D1,Da=D2); (Db=D2,Da=D3); (Db=D3,Da=D4); (Db=D4,Da=D5). vedle(U,Da,Db) :- napravo(U,Da,Db) ; napravo(U,Db,Da). posledni(ulice(_,_,_,_,D),D). prostredni(ulice(_,_,D,_,_),D). okUlice(U) :- uliceMaDum(U,dum(_,mff,prolog,_,_)), uliceMaDum(U,dum(red,zcu,_,_,_)), uliceMaDum(U,dum(_,cvut,_,_,pes)), uliceMaDum(U,dum(_,up,_,microsoft,_)), posledni(U,dum(_,mu,_,_,_)), uliceMaDum(U,dum(_,_,swift,apple,_)), uliceMaDum(U,dum(yellow,_,haskell,_,_)), uliceMaDum(U,dum(_,_,lisp,_,papusek)), uliceMaDum(U,dum(green,_,_,google,_)), vedle(U, dum(_,_,lisp,_,_), dum(_,_,_,_,kocka)), vedle(U, dum(_,_,_,_,kun), dum(_,_,haskell,_,_)), vedle(U, dum(_,_,fsharp,_,_), dum(_,_,_,ibm,_)), napravo(U, dum(green,_,_,_,_), dum(orange,_,_,_,_)), vedle(U, dum(_,mu,_,_,_), dum(blue,_,_,_,_)), prostredni(U, dum(_,_,_,facebook,_)), uliceMaDum(U,dum(_,_,_,_,zebra)). %----------------------------------------------- % akce(+Stav1, +Obj1, +Obj2, -Stav2). % vyleju první akce(s(_,Y), _,_, s(0,Y)). % vyleju druhou akce(s(X,_), _,_, s(X,0)). % naplnim první akce(s(_,Y), Obj1,_, s(Obj1,Y)). % naplnim druhou akce(s(X,_), _,Obj2, s(X,Obj2)). % preleju druhou do prvni, nevejde se akce(s(X,Y), Obj1,_, s(Obj1,Y1)) :- X + Y > Obj1, Y1 is X+Y - Obj1. %preleju druhou do prvni, vejde se akce(s(X,Y), Obj1,_, s(X1,0)) :- X + Y =< Obj1, X1 is X + Y. % preleju prvni do druhy, nevejde se akce(s(X,Y), _,Obj2, s(X1,Obj2)) :- X + Y > Obj2, X1 is X+Y - Obj2. %preleju prvni do druhy, vejde se akce(s(X,Y), _,Obj2, s(0,Y1)) :- X + Y =< Obj2, Y1 is X + Y. %nkroku(+Stav, +Obj1, +Obj2, +PocetKroku, -StavPoNKrocích). nkroku(S, _, _, 0, S). nkroku(S, Obj1, Obj2, N, StavPoN) :- N > 0, akce(S, Obj1, Obj2, S1), N1 is N - 1, nkroku(S1, Obj1, Obj2, N1, StavPoN). % nkroku(+Stav, +Obj1, +Obj2, +PocetKroku, -PoslStavu, -KonStav). nkroku(S, Obj1, Obj2, N, Posl, KonStav) :- nkroku(S, Obj1, Obj2, N, [S], Posl, KonStav). nkroku(S, _,_, 0, Acc, Posl, S) :- reverse(Acc,Posl). nkroku(S, Obj1, Obj2, N, Acc, Posl, KonStav) :- N > 0, akce(S, Obj1, Obj2, S1), \+member(S1,Acc), N1 is N - 1, nkroku(S1, Obj1,Obj2, N1, [S1|Acc], Posl, KonStav). % vyresID(+PocatecniStav, +Obj1, +Obj2, +KonStav, -Posl). vyresID(PS, Obj1,Obj2, KonStav, Posl) :- vyresID(PS, Obj1,Obj2, 1, KonStav, Posl). % vyresID(+PocatecniStav, +Obj1, +Obj2, +Hloubka,+KonStav, -Posl). vyresID(PS, Obj1,Obj2, Hloubka, KonStav, Posl) :- nkroku(PS, Obj1,Obj2, Hloubka, Posl, KonStav). vyresID(PS, Obj1,Obj2, Hloubka, KonStav, Posl) :- Hloubka1 is Hloubka + 1, Hloubka1 < 50, vyresID(PS, Obj1,Obj2, Hloubka1, KonStav, Posl).
% -- Rozdílové seznamy ----------------------------- naRozdil([],X-X). naRozdil([H|T], [H|L]-X) :- naRozdil(T,L-X). naKlasik(L-[], L). spoj1(L1-X1, L2-X2, L3-X3) :- X1=L2, L3=L1, X3=X2. spoj(L1-L2, L2-X2, L1-X2). % -- FLATTEN ----------------------------------------- flatten([],[]). flatten([X|Xs], Res) :- flatten(X,FlatX), flatten(Xs,FlatXs), append(FlatX,FlatXs,Res), !. flatten(X,[X]). flatten2(Xs,Res) :- difflat(Xs,Res-[]). difflat([],X-X). /* difflat([X|Xs], Res) :- difflat(X,FlatX), difflat(Xs,FlatXs), spoj(FlatX,FlatXs,Res), !.*/ difflat([X|Xs], Res-R) :- difflat(X,Res-FlatXs), difflat(Xs,FlatXs-R), !. difflat(X,[X|XX]-XX). % -- QUICKSORT --------------------------------------- % partition(+Pivot, +Xs, -Maly, -Velky) partition(_, [],[],[]). partition(Pivot, [X|Xs], [X|Maly], Velky) :- X =< Pivot, partition(Pivot, Xs, Maly, Velky). partition(Pivot, [X|Xs], Maly, [X|Velky]) :- X > Pivot, partition(Pivot, Xs, Maly, Velky). qsort([],[]). qsort([X|Xs], Res) :- partition(X, Xs, Maly, Velky), qsort(Maly, MalySorted), qsort(Velky, VelkySorted), append(MalySorted, [X|VelkySorted], Res). quicksort(Xs, Res) :- qs(Xs, Res-[]),!. qs([],X-X). qs([X|Xs], Res-R) :- partition(X,Xs, Maly, Velky), qs(Maly, Res-[X|SVelky]), qs(Velky, SVelky-R). % -- BINARNI STROMY ------------------------------------------------ % t(t(nil,2,nil),1,t(nil,3,nil)) % t(t(t(nil,4,nil),2,t(nil,5,nil)),1,t(nil,3,nil)) preList(nil, []). preList(t(L,Node,R), [Node|Res]) :- preList(L,LRes), preList(R,RRes), append(LRes,RRes,Res). preList2(Tree,Xs) :- preDL(Tree,Xs-[]). preDL(nil, X-X). preDL(t(L,Node,R), [Node|Res]-Tail) :- preDL(L, Res-RRes), preDL(R, RRes-Tail). inList(nil, []). inList(t(L,Node,R), Res) :- inList(L, LRes), inList(R, RRes), append(LRes,[Node|RRes],Res). inList2(Tree,Xs) :- inDL(Tree,Xs-[]). inDL(nil, X-X). inDL(t(L,Node,R), Res-Tail) :- inDL(L, Res-[Node|RRes]), inDL(R, RRes-Tail). postList(nil, []). postList(t(L,Node,R), Res) :- postList(L,LRes), postList(R,RRes), append(RRes,[Node],RResNode), append(LRes,RResNode,Res). postList2(Tree,Xs) :- postDL(Tree, Xs-[]). postDL(nil, X-X). postDL(t(L,Node,R), Res-Tail) :- postDL(L, Res-RRes), postDL(R, RRes-[Node|Tail]). preorder(t(_,X,_),X). preorder(t(L,_,_),X) :- preorder(L,X). preorder(t(_,_,R),X) :- preorder(R,X). inorder(t(L,_,_),X) :- inorder(L,X). inorder(t(_,X,_),X). inorder(t(_,_,R),X) :- inorder(R,X). postorder(t(L,_,_),X) :- postorder(L,X). postorder(t(_,_,R),X) :- postorder(R,X). postorder(t(_,X,_),X).
numBinOp(+). numBinOp(-). numBinOp(*). numBinOp(/). logBinOp(=). logBinOp(\=). logBinOp(=<). logBinOp(>=). logBinOp(<). logBinOp(>). def(inc, fun(x,[+,x,1])). def(fac, fun(n,[if,[=,n,0],1,[*,n,[fac,[-,n,1] ] ]] ) ). fromList([F|Xs], Term) :- fromList(Xs, F, Term). fromList([],Acc,Acc). fromList([X|Xs],Acc,Term) :- fromList(Xs,a(Acc,X),Term). stepPlusOp(Term, Res) :- Term = a(a(+,X),Y), number(X), number(Y), Res is X + Y. stepBinOp(Term, Res) :- Term = a(a(Op,X),Y), number(X), number(Y), ( logBinOp(Op), logOperate(Term,Res) ; numBinOp(Op), numOperate(Term,Res) ). logOperate(a(a(Op,X),Y), true) :- call(Op,X,Y),!. logOperate(a(a(_,_),_), false). numOperate(a(a(Op,X),Y), Res) :- OpTerm =.. [Op,X,Y], Res is OpTerm. step(X, Code) :- def(X,Code). step( a(a(a(if,true),X),_), X). step( a(a(a(if,false),_),Y), Y). step(Term,Res) :- stepBinOp(Term, Res). step(a(M,N), a(M2,N)) :- step(M,M2). step(a(M,N), a(M,N2)) :- step(N,N2). step( a(fun(X,M) , N), Res) :- sub(M,X,N,Res). step(Xs, Res) :- fromList(Xs, Term), step(Term,Res). eval(Term, Res) :- step(Term,Term2), eval(Term2,Res),!. eval(Term, Term). stepEval(Term,Term). stepEval(Term, Res) :- step(Term,Term2), stepEval(Term2, Res). % sub(+Term, +Var, +NewSubterm, -NewTerm) sub(a(M,N), V, T, a(M2,N2)) :- sub(M,V,T,M2), sub(N,V,T,N2),!. sub(Xs, V, T, M2) :- fromList(Xs,M), sub(M,V,T,M2),!. sub(fun(X,M), X, _, fun(X,M)) :- !. sub(fun(X,M), V, T, fun(X,M2)) :- sub(M,V,T,M2),!. sub(X, X, T, T) :- !. sub(X,_,_,X) :- !.
Toto jsme dělali na třetím cvičení (ještě přididám podrobnější komentář..) :
conc([],Ys,Ys). conc([X|Xs],Ys,[X|XsYs]) :- conc(Xs,Ys,XsYs). pridejz(X,Xs,Res) :- conc([X],Xs,Res). pridejk(X,Xs,Res) :- conc(Xs,[X],Res). last(Xs,Last) :- conc(_,[Last],Xs). mem(X,Xs) :- conc(_,[X|_],Xs). remove(X,[X|Ys],Ys). remove(X,[Y|Ys],[Y|Zs]) :- remove(X,Ys,Zs). insert(X,Xs,Ys) :- remove(X,Ys,Xs). perm1([],[]). perm1(Xs,[X|SubPerm]) :- remove(X,Xs,Rest), perm1(Rest,SubPerm). perm2([],[]). perm2([X|Xs],Perm) :- perm2(Xs,SubPerm), remove(X,Perm,SubPerm). %------------------------------------------------------- rev(Xs,Res) :- rev(Xs,[],Res). rev([],A,A). rev([X|Xs], A, Res) :- rev(Xs, [X|A], Res). %palyndrom(+Xs): palindrom(X):-rev(X,X). %containsOnly(?Xs,+Abc). containsOnly([],_). containsOnly([X|Xs], Abc) :- containsOnly(Xs, Abc), member(X, Abc). palyndromFrom(Abc,Xs) :- palindrom(Xs), containsOnly(Xs,Abc). %------------------------------------------------------- %zabal(+Xs,-ZXs). zabal([],[]). zabal([X|Xs], [[X] | ZXs]) :- zabal(Xs,ZXs). %pridejHlavy(+Hs,+Ts,-HTs). pridejHlavy(Hs,[],Ss) :- zabal(Hs,Ss). pridejHlavy([H|Hs],[T|Ts],[[H|T]|HTs]) :- pridejHlavy(Hs,Ts,HTs). %transp(+M,-TM). transp([],[]). transp([Row|Rows], Res) :- transp(Rows,SubRes), pridejHlavy(Row,SubRes,Res),!. %sum(+Xs,-Sum) sum(Xs,Sum) :- sum(Xs,0,Sum). sum([],A,A). sum([X|Xs],A,Sum) :- A2 is A + X, sum(Xs,A2,Sum). % "Xs*Ys = Zs po složkách" listKrat([],[],[]). listKrat([X|Xs],[Y|Ys],[Z|Zs]) :- Z is X * Y, listKrat(Xs,Ys,Zs). listOp(_,[],[],[]). listOp(Op,[X|Xs],[Y|Ys],[Z|Zs]) :- call(Op,X,Y,Z), listOp(Op,Xs,Ys,Zs). dotProd(Xs,Ys,Res) :- listKrat(Xs,Ys,Zs), sum(Zs,Res). listOp1N(_,_,[],[]). listOp1N(Op,X,[Y|Ys],[Z|Zs]) :- call(Op,X,Y,Z), listOp1N(Op,X,Ys,Zs). listOpMN(_,[],_,[]). listOpMN(Op, [X|Xs], Ys, [R|Rs]) :- listOp1N(Op,X,Ys,R), listOpMN(Op,Xs,Ys,Rs). mProd(M1, M2, Res) :- transp(M2,TM2), listOpMN(dotProd, M1, TM2, Res).
Na druhém cvičení jsme si ukázali jak si lze v prologu zavést "syntaktická" přirozená čísla ve stylu peanovy aritmetiky, jak na nich udělat operace (a to že to jde různými způsoby):
cislo(o). cislo(s(X)) :- cislo(X). plus(o,X,X) :- cislo(X). plus(s(X),Y,s(Z)) :- plus(X,Y,Z). minus(Z,X,Y) :- plusko(X,Y,Z). dvakrat(X,Y) :- plusko(X,X,Y). krat(o,Y,o) :- cislo(Y). krat(s(X), Y, Z) :- plus(Y,P,Z), krat(Y,X,P). pow(Y,o,s(o)) :- cislo(Y). pow(Y,s(X),Z) :- krat(Y,P,Z), pow(Y,X,P). mensiNez(o,s(Y)) :- cislo(Y). mensiNez(s(X),s(Y)) :- mensiNez(X,Y). mensiNez2(X,s(X)) :- cislo(X). mensiNez2(X,s(Y)) :- mensiNez2(X,Y).
Za (vedlejší) domácí úkol bylo si rozmyslet použití krat(-X,-Y,+Z), tedy co způsobuje že některé definice fungují a jiné ne.
Dále jsme procvičili několik jednoduchých operací na seznamech.
prvek(X,[X|_]). prvek(X,[_|Xs]) :- prvek(X,Xs). pridejNaZacatek(X, Xs, [X|Xs]). pridejNaKonec(X, [], [X]). pridejNaKonec(X, [Y|Ys], [Y|YsX]) :- pridejNaKonec(X, Ys, YsX).
Za domácí úkol bylo implementova operaci zřetězení dvou seznamů, tak aby fungovala jako:
zretez(+X,+Y,-Z) ?- zretez([1,2],[3,4,5],X). X = [1, 2, 3, 4, 5]
ale také jako:
zretez(?X,?Y,+Z) ?- zretez(X,Y,[1,2]). X = [], Y = [1,2]; X = [1], Y = [2]; X = [1,2], Y = []
Na prvním cvičení jsme si ukázali základní práci s prologem na příkladu rodiných vztahů.
Za domácí úkol bylo implementova tři netriviální příbuzenské vztahy, zde je příklad jak několik takových vztahů může vypadat pro rodinu Simpsonových:
% == Databáze elementárních vztahů ======== muz(homer). muz(bart). muz(abe). muz(herb). muz(clancy). zena(marge). zena(lisa). zena(maggie). zena(mona). zena(jackie). zena(patty). zena(selma). zena(ling). potomek(homer, abe). potomek(homer, mona). potomek(bart, homer). potomek(bart, marge). potomek(lisa, homer). potomek(lisa, marge). potomek(maggie, homer). potomek(maggie, marge). potomek(herb, abe). potomek(herb, mona). potomek(patty, clancy). potomek(patty, jackie). potomek(selma, clancy). potomek(selma, jackie). potomek(marge, clancy). potomek(marge, jackie). potomek(ling, selma). manzel(abe, mona). manzel(homer, marge). manzel(clancy, jackie). % == Odvozené vztahy ====================== manzele_sym(X,Y) :- manzel(X,Y);manzel(Y,X). otec(O,D) :- potomek(D,O), muz(O). matka(M,D) :- potomek(D,M), zena(M). syn(S,R) :- potomek(S,R), muz(S). dcera(D,R) :- potomek(D,R), zena(D). sourozenec(X,Y) :- potomek(X,R), potomek(Y,R), X \= Y. bratr(X,Y) :- muz(X), sourozenec(X,Y). sestra(X,Y) :- zena(X),sourozenec(X,Y). potomek2(X,M,O) :- potomek(X,M), potomek(X,O), zena(M), muz(O). hardSourozenec(X,Y) :- potomek2(X,M,O), potomek2(Y,M,O), X\=Y. hardBratr(X,Y) :- muz(X), hardSourozenec(X,Y). hardSestra(X,Y) :- zena(X), hardSourozenec(X,Y). vnoucek(X,PraR) :- potomek(X,R), potomek(R,PraR). teta(X,Y) :- sestra(X,M), potomek(Y,M). tchan(X,Y) :- manzele_sym(Y,A), otec(X,A). cousin(X,Y) :- potomek(X,R), sourozenec(R,T), potomek(Y,T). sestrenice(X,Y) :- zena(X), cousin(X,Y). bratranec(X,Y) :- muz(X), cousin(X,Y). snacha(X,Y) :- zena(X), manzele_sym(X,A), potomek(A,Y). snacha2(X,Y):- syn(A,Y), manzele_sym(X,A). neter(X,Y) :- zena(X), potomek(X,R), sourozenec(R,Y). svagrova(X,Y) :- sestra(X,M), manzele_sym(M,Y). svagrova(X,Y) :- zena(X), manzele_sym(X,B), bratr(B,Y).