Práce se seznamy (pokračování)



-- skytí knihovních funkcí které napíšeme
import Prelude hiding
   (unzip, zipWith, splitAt, elem, break)


-- ilustrace použití let a where
cislo k =
    let cisla = 1 : merge3 (map (2*) cisla) (map (3*) cisla) (map (5*) cisla)
    in cisla !! k

cislo' k = cisla !! k where
    cisla = 1 : merge3 (map (2*) cisla) (map (3*) cisla) (map (5*) cisla)

-- | sleje tři neklesající posloupnosti a maže duplikáty
merge3 (a:as) (b:bs) (c:cs)
    | a<b && a<c = a : merge3 as (b:bs) (c:cs)
    | b<a && b<c = b : merge3 (a:as) bs (c:cs)
    | c<a && c<b = c : merge3 (a:as) (b:bs) cs
    | a==b || a==c = merge3 as (b:bs) (c:cs)
    | b==c = merge3 (a:as) bs (c:cs)




unzip :: [(a, b)] -> ([a], [b])
unzip [] = ([],[])
unzip ((x,y):z) = (x:a, y:b) where (a,b) = unzip z


zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith _ [] _ = []
zipWith _ _ [] = []
zipWith f (x:xs) (y:ys) = (f x y) : zipWith f xs ys

zvětšuj = zipWith (+) [1..]

splitAt :: Int -> [a] -> ([a], [a])
splitAt 0 xs = ([], xs)
splitAt _ [] = ([], [])
splitAt p (x:xs) = if p>0 then let (ys,zs) = splitAt (p-1) xs in (x:ys, zs)
                              else error "Negative index"


elem :: Eq a => a -> [a] -> Bool
elem a [] = False
elem a (x:xs) = a == x || elem a xs

-- rozdělení seznamu na pozici kde poprvé uspěje predikát
break :: (a -> Bool) -> [a] -> ([a], [a])
break _ [] = ([], [])
break f (a:as)
    | f a = ([], (a:as))
    | otherwise = let (b,c) = break f as in (a:b, c)


-- funkce níže nejsou z Prelude ale z Data.List

-- funkce s trochu zvláštním významem, asi nejlépe vysvětlena kódem
union :: Eq a => [a] -> [a] -> [a]
union uPS hOPS
    = uPS ++ filter (not . (`elem` uPS)) hOPS

    -- = uPS ++ filter (\x -> not  (x `elem` uPS)) hOPS


-- rozdělení prvků podle toho zda splňují predikát
partition :: (a -> Bool) -> [a] -> ([a], [a])
partition _ [] = ([], [])
partition f (h:t) = if f h then (h:(fst list), (snd list))
                           else ((fst list), h:(snd list))
                           where list = partition f t


findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices = findIndices' 0

findIndices' _ _ [] = []
findIndices' a f (h:t) = (if f h then [a] else []) ++ findIndices' (a+1) f t