Szövegformázás

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! A függvények definíciójában lehet, sőt javasolt is alkalmazni a korábban definiált függvényeket (függetlenül attól, hogy sikerült-e azokat megadni)!

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 egy egyszerű formázó függvényt kell elkészítenünk, amely egyébként a UNIX fmt(1) parancsának is az alapja. Ennek az a feladata, hogy a kapott szöveget az adott hosszúságú sorokra tördelje, valamint a mondatvégi írásjelek után két szóközzel válassza el egymástól a mondatokat. (Ez a konvenciót az Emacs szövegszerkesztő is alkalmazza, így ismeri fel a mondatokat a szövegben.)

A tördeléshez alkalmazott optimális sorhosszat a felhasználó adja meg, a megírandó függvény feladata tehát közel akkora hosszú sorok készítése. Az eredeti szövegben lehetnek sortörések (sorok), de ezeket a program figyelmen kívül hagyja. Szavakat nem tudunk elválasztani, így ha egyetlen túl hosszú szavunk jut egy adott sorra, akkor értelemszerűen nem tudjuk garantálni, hogy a sor nem lesz hosszabb a megadottnál.

Mondatjel felismerése (1 pont)

Elsőként készítenünk kell egy függvényt, amellyel meg tudjuk állapítani egy karakterről, hogy mondatjel vagy sem. Mondatjelnek tekintjük a kérdőjelet, a felkiáltójelet és a pontot.

isEndMark :: Char -> Bool

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

Szavak összefűzése (2 pont)

Készítsünk egy olyan függvényt, amely hasonlóan működik a Prelude modul unwords függvényéhez, azonban a mondatjelek vagy mondatjelre végződő szavak után nem egyetlen szóközt, hanem kettőt tesz! Ügyeljünk arra, hogy erre csak akkor van szükség, ha az adott szó nem a paraméterként szolgáló, szavakat tartalmazó lista utolsó eleme!

(Megjegyzés: A fólián sajnos nem látszik, de példabeli mondatvégeknél tényleg két szóköz szerepel!)

unwords' :: [String] -> String

Test>
"Hello world! This is my Haskell program." :: String
Test>
"A Prelude identifier: Prelude.length." :: String
Test>
[] :: String

Távolság (1 pont)

Adjunk meg egy függvényt, amellyel meg tudjuk határozni két szám távolságát! Ha x kisebb, mint y, akkor adjuk vissza a kettő különbségének abszolút értékének ötszörösét, ellenkező esetben csak a kettő különségét. Vegyük észre, hogy az így eredmény mindig nemnegatív lesz!

d :: (Ord a, Num a) => a -> a -> a

Test>
4 :: Integer
Test>
40 :: Integer

Egy sorba beférő szavak (4 pont)

Az előbbiek felhasználásával most írjunk egy olyan függvényt, amely egy adott sorhossz és szavak listája mellett megadja a sorba még beférő szavakat! Ezek lényegében azok lesznek, amelyeket összefűzve legközelebb kerülünk az optimális sorhosszhoz. Egyetlen szó esetén az eredmény automatikusan maga a szó lesz, mivel feltételezzük, hogy egy szót mindig tudnunk kell betenni a sorba. Az optimális sorhosszhoz való viszonyítást egy kétparaméteres függvény segítségével tudjuk megadni.

fit :: (Int -> Int -> Int) -> Int -> [String] -> [String]

Test>
["This"] :: [String]
Test>
["Moreover..."] :: [String]
Test>
["That", "is"] :: [String]

A szöveg feldarabolása (3 pont)

Miután képesek vagyunk összeszedni az egyes sorokba beférő szavakat, készítsük el azt a függvényt is, amellyel a megadott sorhossz alapján szavak egy listáját soroljuk be sorokba aszerint, hogy még elférnek-e bennük! Vegyük észre, hogy ennél a függvénynél ismét meg kell adni az előbbi feladathoz tartozó távolságfüggvényt is.

cut :: (Int -> Int -> Int) -> Int -> [String] -> [[String]]

Test>
[["This", "is"], ["a", "very"], ["long"], ["text."]] :: [[String]]
Test>
[["This", "is", "a", "very", "long", "text."]] :: [[String]]

Formázás (1 pont)

Végül fogalmazzuk meg a formázási lépéseket összefoglaló függvényünket a korábban definiált műveletek segítségével! Ügyeljünk arra, hogy az eredményben a mondatjelek után továbbra is két szóköznek kell lennie!

format :: Int -> String -> String

Test>
"Hello. This is my text! I want to format it.\n" :: String
Test>
"Hello. This is\nmy text! I want\nto format it.\n" :: String
Test>
"Hello.\nThis is\nmy text!\nI want\nto format\nit.\n" :: String

Pontozás (elmélet + gyakorlat)