Rekurzió

Feladat: Prelude.sum [*]

Definiáljuk újra a sum függvényt, amely összegez egy számlistát!

sum :: Num a => [a] -> a

Test>
0 :: Int
Test>
55 :: Int

Feladat: Prelude.last [*]

Definiáljuk újra a last függvényt, amely visszaadja egy lista utolsó elemét!

last :: [a]{-nemüres-} -> a

Test>
't' :: Char

Feladat: Prelude.init [*]

Definiáljuk újra az init függvényt, amely egy lista összes elemét visszaadja, az utolsót kivéve!

init :: [a]{-nemüres-} -> [a]

Test>
"las" :: [Char]

Feladat: Prelude.minimum [*]

Definiáljuk újra a minimum függvényt, amely több elem minimumát adja vissza! Használjuk a min függvényt: ez két elem minimumát adja vissza.

minimum :: Ord a => [a]{-véges, nemüres-} -> a

Test>
1 :: Int

Feladat: Prelude.concat [*]

Definiáljuk újra a concat függvényt, amely sok listát fűz össze!

concat :: [[a]] -> [a]

Test>
[] :: [()]
Test>
[1, 2, 3, 4, 5, 6] :: [Int]
Test>
[1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5] :: [Integer]

Működés:

Feladat: (Prelude.++) [*]

Definiáljuk újra a (++) operátort, amely két listát fűz össze!

(++) :: [a] -> [a] -> [a]

Test>
[1, 2, 3, 4, 5, 7, 8, 9, 10] :: [Int]
Test>
True :: Bool

Feladat: Összefésülés

Definiáljuk az összefésülést! Az eredmény lista elemei a bemenő listák váltogatott elemei lesznek.

merge :: [a] -> [a] -> [a]

Test>
[1, 4, 2, 5, 3, 6] :: [Integer]
Test>
[4, 5, 6] :: [Integer]
Test>
[3, 0, 4] :: [Integer]

Feladat: Prelude.zip [*]

Definiáljuk újra az elemenkénti párosítást!

zip :: [a] -> [b] -> [(a,b)]

Test>
[(1, 'a'), (2, 'b')] :: [(Integer, Char)]
Test>
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')] :: [(Integer, Char)]
Test>
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10), (11, 12), (13, 14), (15, 16), (17, 18), (19, 20), (21, 22), (23, 24), (25, 26), (27, 28), (29, 30), (31, 32), (33, 34), (35, 36), (37, 38), (39, 40), (41, 42), (43, 44), (45, 46), (47, 48), (49, 50), (51, 52), (53, 54), (55, 56), (57, 58), (59, 60), (61, 62), (63, 64), (65, 66), (67, 68), (69, 70), (71, 72), (73, 74), (75, 76), (77, 78), (79, 80), (81, 82), (83, 84), (85, 86), (87, 88), (89, 90), (91, 92), (93, 94), (95, 96), (97, 98), (99, 100)] :: [(Integer, Integer)]

Feladat: Data.List.isPrefixOf [*]

Definiáljuk újra a Data.List modulbeli isPrefixOf függvényt, amely megállapítja, hogy az egyik szöveg kiegészítése-e a másik!

isPrefixOf :: Eq a => [a] -> [a] -> Bool

Test>
True :: Bool
Test>
True :: Bool
Test>
True :: Bool
Test>
True :: Bool
Test>
True :: Bool

Feladat: Prelude.elem [*]

Definiáljuk újra az elem függvényt, amely megállapítja, hogy egy érték szerepel-e egy listában!

elem :: Eq a => a -> [a]{-véges-} -> Bool

Test>
True :: Bool
Test>
True :: Bool

Feladat: Data.List.nub [*]

Definiáljuk újra a Data.List modulbeli nub függvényt! A nub a többszörös elemeket hagyja el egy listából.

nub :: Eq a => [a] -> [a]

Test>
[1, 2, 3] :: [Integer]
Test>
[1, 3, 2] :: [Integer]

Feladat: Polinom kiértékelése

Értékeljünk ki adott helyen egy együtthatóival megadott polinomot! A számítás alapját a Horner-séma képzi, amelynek megfelelően a polinom általános alakja:

Recursion6f007ffd22661eaa9e68d65b2f84dc23.png

átírható (a számítás szempontjából kedvezőbb) monomiális formára:

Recursion5110b50b054e9e1da1bf0c502f758a7e.png

Ügyeljünk arra, hogy a polinom együtthatói a listában fordított sorrendben szerepelnek, hogy a rekurziót könnyebb legyen felírni.

polinom :: Num a => [a] -> a -> a

Test>
0 :: Integer
Test>
487 :: Integer
Test>
4916 :: Integer

Feladat: Lista feldarabolása

Vágjunk le egy listából adott hosszúságú részeket!

runs :: Int -> [a] -> [[a]]

Test>
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] :: [[Integer]]

Megjegyzés: Használhatjuk a take és drop függvényeket.

Feladat: Feldarabolás másképp [*]

Vágjunk le egy listából adott hosszúságú részeket úgy, hogy a hosszúságokat egy listában kapjuk!

slice :: [Int] -> [a] -> [[a]]

Test>
[[1, 2, 3], [4, 5], [6, 7, 8]] :: [[Integer]]
Test>
[[1, 2, 3], [4, 5], [6, 7, 8], [9, 10], []] :: [[Integer]]

Megjegyzés: Használhatjuk a take és drop függvényeket.

Feladat: Minden n-edik elem

Definiáljuk az every függvényt, amely veszi egy lista minden n-edik elemét!

every :: Int -> [a] -> [a]

Test>
"HloWrd" :: [Char]
Test>
"HlWl" :: [Char]

Megjegyzés: Használhatjuk a drop függvényt.

Feladat: Gyorsrendezés [*]

Definiáljuk a gyorsrendezést (a listát kettébontjuk a fejnél kisebb és nagyobb elemekre)!

qsort :: Ord a => [a] -> [a]

Test>
[1, 2, 3, 4, 6] :: [Integer]
Test>
[1, 1, 2, 6] :: [Integer]

Megjegyzés: A qsort jelen definíciója nem hatékony rendezett és fordítottan rendezett listák esetén.

Recursion5caec50b2eb5112142ee020dc98a172d.png

Piros nyíl: a fejtől kisebb elemek a farokban
Szürke nyíl: a lista feje
Kék nyíl: a fejtől nagyobb elemek a farokban
Zöld nyilak: összefűzés

Véletlenszerű lista:

Recursion677f36fe8687a43b35f6297cff9ec42e.png

Rendezett listákra qsort lineáris futási idejű, mivel két lista összefűzésének ideje egyenesen arányos az első lista hosszával. Ábra:

Recursion1251cc4d1f425d55ca173cccb9c45b60.png

Fordítva rendezett listákra qsort négyzetes futási idejű, mivel két lista összefűzésének ideje egyenesen arányos az első lista hosszával. Ábra:

Recursionf555b9e42e33335dbae34d1dc42732ec.png

Feladat: Data.List.tails [*]

Állítsuk elő egy lista összes lehetséges végződését! (A Data.List modulban már definiált.)

tails :: [a] -> [[a]] 

Test>
["abc", "bc", "c", []] :: [[Char]]
Test>
[[1, 2, 3, 4], [2, 3, 4], [3, 4], [4], []] :: [[Integer]]

Feladat: Data.List.inits

Állítsuk elő egy lista összes prefixét! (A Data.List modulban már definiált.)

inits :: [a] -> [[a]] 

Test>
[[], "a", "ab", "abc"] :: [[Char]]
Test>
[[], [1], [1, 2], [1, 2, 3]] :: [[Integer]]

Feladat: Elem törlései listából

Töröljünk egy elemet egy listából az összes lehetséges módon!

deletions :: [a] -> [[a]]

Test>
True :: Bool
Test>
[[]] :: [[Integer]]
Test>
[[2, 3, 2], [1, 3, 2], [1, 2, 2], [1, 2, 3]] :: [[Integer]]

Feladat: Elem beszúrásai listába

Szúrjunk be egy elemet egy listába az összes lehetséges módon!

insertions :: a -> [a] -> [[a]]

Test>
[[1]] :: [[Integer]]
Test>
[[1, 2, 3], [2, 1, 3], [2, 3, 1]] :: [[Integer]]

Feladat: Permutációk

Adjuk meg egy lista összes permutációját!

permutations :: [a] -> [[a]]

Test>
["123", "213", "231", "132", "312", "321"] :: [[Char]]

[“123”,“213”,“231”,“132”,“312”,“321”]


Recursionc1245aa36815634046f21e815a3b9e0d.png

Szürke nyilak: lista szétbontása fejre és farokra
Piros nyilak: permutáció (rekurzív hívás)
Kék nyilak: insertions hívás

További ábra:

Recursion41ba73aceaa29ed3ccdbc7361a3ba3bf.png

Feladat: Egész szám felbontása összegekre

part :: Int -> [[Int]]

Test>
[[]] :: [[Int]]
Test>
[[1]] :: [[Int]]
Test>
[[2], [1, 1]] :: [[Int]]
Test>
[[3], [2, 1], [1, 2], [1, 1, 1]] :: [[Int]]
Test>
[[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] :: [[Int]]

Bontsunk fel egy egész számot összegekre az összes lehetséges módon!

Az összeget egy listaként ábrázoljuk (például az 1 + 2 + 4 összeget így: [1, 2, 4]).

Az összegben számítson a sorrend (például a 1 + 2 és 2 + 1 különböző felbontások).

Segítség. Az algoritmus a következő:

Ha 4-et akarjuk felbontani az összes lehetséges módon, akkor a következő tesszük:

Minden egyes esetben rekurzívan hívtuk a part függvényt. A 4 eset eredményeit összefűzzük.