Szöveg átírásai

Általános tudnivalók

Használható segédanyagok: GHC dokumentáció, Hoogle, a tárgy honlapja és a BE-AD rendszerbe feltöltött beadandók. Ha bármi kérdés, észrevétel felmerül, azt a felügyelőnek jelezzétek, NE a mellettetek ülőnek!

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!

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

A feladat összefoglaló leírása

A feladat megoldása során egy szöveget feldolgozó/átalakító függvényt és az ehhez tartozó segédfüggvényeket fogunk megadni. Miután ezeket megadtuk, egy jóval hatékonyabb megoldást fogunk keresni, illetve megadni.

Adott egy g függvény, amely köré a feladat épül. A g függvény segítségével egy karakterből egy szöveget tudunk képezni. A függvény értelmezési tartománya a következő karakterekre korlátozott: 'a', 'b', 'c'.

Rewriter327953db0ccea909e0e85c2aec47a3dc.png

A g függvény megadása (1 pont)

Definiáljuk az fenteb megadott g (parciális) függvényt!

g :: Char -> [Char]

Test>
"bc" :: [Char]
Test>
⊥₁ :: [Char]
⊥₁: g: Illegal character!
CallStack (from HasCallStack):
  error, called at ./Rewriter.lhs:60:11 in main:Rewriter

A g függvény alkalmazása (1 pont)

Adjuk meg azt a függvényt, amely a legalább kételemű listák esetén az első elem g szerinti képét a lista végéhez fűzi, a második elemet pedig elhagyja!

step :: [Char] -> [Char]

Test>
"abc" :: [Char]
Test>
"baa" :: [Char]
Test>
[] :: [Char]

A g függvény többszöri alkalmazása (2 pont)

Adjuk meg azt a függvényt, amely n darab 'a' karakteren végtelenszer alkalmazza a korábban megadott függvényt!

steps :: Int -> [[Char]]

Test>
["aaaaa", "aaabc", "abcbc", "cbcbc", "cbcaaa", "caaaaaa", "aaaaaaaa", "aaaaaabc", "aaaabcbc", "aabcbcbc", "bcbcbcbc", "bcbcbca", "bcbcaa", "bcaaa", "aaaa", "aabc", "bcbc", "bca", "aa", "bc", "a", [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], …, ……] :: [[Char]]

Üres sorozatok elhagyása (2 pont)

Adjuk meg azt a függvényt, amely az előbb megadott steps függvény eredményének végéről elhagyja az üres sorozatokat!

tag :: Int -> [[Char]]

Test>
["aa", "bc", "a"] :: [[Char]]
Test>
["aaa", "abc", "cbc", "caaa", "aaaaa", "aaabc", "abcbc", "cbcbc", "cbcaaa", "caaaaaa", "aaaaaaaa", "aaaaaabc", "aaaabcbc", "aabcbcbc", "bcbcbcbc", "bcbcbca", "bcbcaa", "bcaaa", "aaaa", "aabc", "bcbc", "bca", "aa", "bc", "a"] :: [[Char]]

A tisztán 'a' karakterből álló sorozatok hossza (3 pont)

Definiáljuk azt a függvényt, amely a tag függvény eredményéből megadja azon listák hosszát, amelyben minden karakter 'a'!

tagA :: Int -> [Int]

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

A tag függvény lehetséges felgyorsítása

A ,,jelenség’’ fő oka a (++) operátor, mivel ennek az időigénye egyenesen arányos az első lista hosszával!

A továbbiakban mepróbáljuk felgyorsítani a (++) műveletet, ha rövid a második lista!

Adott a következő reprezentáció:

type S a = ([a], [a])

Konverzió: S a típusból lista (1 pont)

Adjuk meg az S a típusú értéket listává ([a]) alakító függvényt! Ne feledkezzünk meg róla, hogy a reprezentációban a második lista fordított sorrendben tartalmazza az elemeit!

fromS :: S a -> [a]

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

Konverzió: listából S a típus (1 pont)

Adjuk meg azt a függvényt, amely egy listát S típusú értékké alakít át!

toS :: [a] -> S a

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

Bővítés (2 pont)

Adjuk meg azt a függvényt, amely segítségével hozzá tudunk fűzni egy új listát a meglévőekhez!

appendTo :: S a -> [a] -> S a

Test>
([1, 2, 3, 4, 5], [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6]) :: S Integer

Nézzük meg az új reprezentációval elért hatékonyságot!

A korábban említett kifejezés túllépi a megengedett időkorlátot:

Test>
⊥₁ :: Int
⊥₁: timeout at 0%

Míg, ha az új reprezentációt használjuk, a kiértékelés megtörténik a megengedett időn belül:

Test>
10000 :: Int

Elem eldobása (1 pont)

Adjuk meg azt a függvényt, amely eldob egy elemet az új reprezentációval adott listából!

drop1 :: S a -> S a

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

Elemek eldobása (2 pont)

Adjuk meg azt a függvényt, amely tetszőleges számú elemet eldob az új reprezentációval adott listából!

dropN :: Int -> S a -> S a

Test>
([6, 7, 8, 9, 10], []) :: S Integer
Test>
([11, 12, 13, 14, 15], []) :: S Integer

Gyorsított step (3 pont)

Adjuk meg azt a step függvényt azon változatát, amely az új reprezentációval dolgozik!

Emlékeztető: a legalább két elemű listák esetén az első elem g szerinti képét a lista végéhez fűzi, a második elemet pedig elhagyja.

step' :: S Char -> S Char

Test>
("b", "a") :: S Char
Test>
("ba", "a") :: S Char
Test>
("ba", "aaa") :: S Char

Vessük össze az eredeti megoldással!

A korábbi step művelet kiértékelése nem fér bele a rendszer által támasztott időkorlátba.

Test>
⊥₁ :: [Char]
⊥₁: timeout at 0%

Ellentétben az új, gyorsított step kiértékelése nem okoz gondot:

Test>
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb" ++ […, ……] :: [Char]

Gyorsított tag (4 pont)

Adjuk meg azt a függvényt, amely az előbb megadott step függvényt végtelenszer alkalmazza egymás után, és az eredményének végéről elhagyja az üres sorozatokat!

tag' :: Int -> [[Char]]

Test>
["aaa", "abc", "cbc", "caaa", "aaaaa", "aaabc", "abcbc", "cbcbc", "cbcaaa", "caaaaaa", "aaaaaaaa", "aaaaaabc", "aaaabcbc", "aabcbcbc", "bcbcbcbc", "bcbcbca", "bcbcaa", "bcaaa", "aaaa", "aabc", "bcbc", "bca", "aa", "bc", "a"] :: [[Char]]
Test>
["aaaa", "aabc", "bcbc", "bca", "aa", "bc", "a"] :: [[Char]]

Vessük össze az eredeti megoldással!

A korábbi tag művelet kiértékelése nem fér bele a rendszer által támasztott időkorlátba.

Test>
⊥₁ :: Int
⊥₁: timeout at 0%

Ellentétben az új, gyorsított tag’ kiértékeleése nem okoz gondot.

Test>
40657 :: Int

Pontozás