Tömbök

Használható segédanyagok: Haskell könyvtárainak dokumentációja, (lokális!) Hoogle, a tárgy honlapja és a BE-AD rendszerbe feltöltött beadandók. Ha bármilyen kérdés, észrevétel felmerül, azt a felügyelőknek kell jelezni, NEM a diáktársaknak!

A feladatok egymásra épülnek ezért érdemes ezeket a megadásuk sorrendjében megoldani, de legalább megérteni az aktuális feladatot megelőző feladatokat!

Tekintve, hogy a tesztesetek, bár odafigyelés mellett íródnak, nem fedik le minden esetben a függvény teljes működését, határozottan javasolt még külön próbálgatni a megoldásokat beadás előtt, vagy megkérdezni a felügyelőket!

Részpontszámokat csak az elégséges szint elérése után lehet kapni!

A feladat összefoglaló leírása

Ebben a feladatban tömbök leírását és kombinálását megvalósító függvényekkel fogunk dolgozni. A tömböket a Block algebrai adattípus definiálja:

data Block a = Block Int Int [[a]]
  deriving (Eq, Show, Data, Typeable)

Itt a tömbökhöz tartozóan nem csak a bennük tárolt elemeket tároljuk el listák listájaként, hanem a hozzájuk tartozó dimenziókat. Ennek köszönhetően ellenőrizni tudjuk, hogy a megfelelő módon kombináljuk-e a tömböket.

Üres tömb (1 pont)

Adjuk meg azt a függvényt, amellyel n × m méretű tömböket tudunk a fentebb megadott ábrázolási mód szerint létrehozni!

blockOf :: Int -> Int -> a -> Block a

Test>
Block 1 1 ["*"] :: Block Char
Test>
Block 8 8 ["########", "########", "########", "########", "########", "########", "########", "########"] :: Block Char

Tömbök egymás felé helyezése (1 pont)

Készítsük el azt a függvényt, amely két tömböt rak egymás felé! Ezt viszont csak akkor tudjuk megtenni, ha a tömbök egyenlő szélességűek. Ellenkező esetben a műveletnek nincs eredménye, amelyet a Maybe típus jelöl.

above :: Block a -> Block a -> Maybe (Block a)

Test>
Just (Block 1 2 ["#", "*"]) :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Just (Block 2 3 ["##", "**", "**"]) :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Just (Block 1 4 ["#", "*", "*", "x"]) :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)

Megjegyzések:

A Maybe típus definíciója:

data Maybe a = Just a | Nothing

A (>>=) operátor segítségével tudunk Maybe értékeket egyszerűen kombinálni. A definíciója is egyszerű:

(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing
Just x  >>= f = Just (f x)

Például:

Test>
Just 2 :: Maybe Integer
Test>
Nothing :: Maybe Integer

Tömbök egymás mellé helyezése (1 pont)

Készítsük el azt a függvényt, amely két tömböt rak egymás mellé! A művelet az above definíciójához hasonlóan csak akkor legyen lehetséges, ha a két tömb egyenlő magasságú. Ellenkező esetben a műveletnek nincs eredménye, ezt a Maybe segítségével jelöljük.

nextTo :: Block a -> Block a -> Maybe (Block a)

Test>
Just (Block 2 1 ["#*"]) :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Just (Block 3 2 ["#**", "#**"]) :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Just (Block 4 1 ["##*x"]) :: Maybe (Block Char)

Hajtogatás Maybe típusra (4 pont)

Definiáljuk a foldr1 függvényt úgy, hogy képes legyen Maybe típusú eredményt visszaadó függvényt is kezelni!

foldr1M :: (a -> a -> Maybe a) -> [a] -> Maybe a

Test>
Nothing :: Maybe Int
Test>
Just 55 :: Maybe Int
Test>
Nothing :: Maybe Int

Több tömb egymás fölé helyezése (1 pont)

Terjesszük ki az above függvényt tetszőleges mennyiségű elemre! Ezt egy lista segítségével oldjuk meg; amennyiben a listának nincs egyetlen eleme sem, úgy Nothing az eredmény.

vcat :: [Block a] -> Maybe (Block a)

Test>
Nothing :: Maybe (Block Char)
Test>
Just (Block 2 7 ["##", "##", "##", "**", "**", "**", "**"]) :: Maybe (Block Char)
Test>
Just (Block 1 8 ["#", "*", "*", "x", "x", "x", "x", "s"]) :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)

Több tömb egymás mellé helyezése (1 pont)

Terjesszük ki a nextTo függvényt tetszőleges mennyiségű elemre! Hasonlóan a vcat függvényhez, ezt itt is egy lista segítségével oldjuk meg; amikor a listának nincs eleme, az eredmény Nothing.

hcat :: [Block a] -> Maybe (Block a)

Test>
Nothing :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)

Just értékek összegyűjtése (1 pont)

Készítsünk egy függvény, amellyel ki tudjuk gyűjteni a Just adatkonstruktorral létrehozott értékeket egy Maybe értékeket tartalmazó listából! Térjen vissza a Nothing értékkel, ha van legalább egy Nothing elem van a listában. Azaz a függvénynek csak akkor legyen eredménye, ha benne minden elemet a Just adatkonstruktorba csomagoltuk.

foldMaybes :: [Maybe a] -> Maybe [a]

Test>
Just [] :: Maybe [Int]
Test>
Nothing :: Maybe [Int]
Test>
Nothing :: Maybe [[Char]]
Test>
Just [True, False, True, False] :: Maybe [Bool]

n × m tömb összerakása sorfolytonosan (2 pont)

Végezetül adjuk meg annak a függvénynek a definícióját, amely képes tömbök listájának listájából egy összefüggő tömbök készíteni az above és nextTo függvények alkalmazása mentén! Értelemszerűen, ha valamelyik ponton nem illeszkednek a tömbök, úgy az eredménye is Nothing lesz.

matrix :: [[Block a]] -> Maybe (Block a)

Test>
Nothing :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)
Test>
Just (Block 6 1 ["#**xxx"]) :: Maybe (Block Char)
Test>
Just (Block 6 2 ["#**xxx", "zzzzss"]) :: Maybe (Block Char)
Test>
Nothing :: Maybe (Block Char)

Pontozás (elmélet + gyakorlat)