Római számok

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!

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ározattan javasolt még külön próbálgatni a megoldásokat beadás előtt, vagy megkérdezni a felügyelőket!

A feladat összefoglaló leírása

A feladat konvertálás hagyományos arab és római számok között, valamint római számok szabványos alakra hozása. A római számokat a következő típusok segítségével ábrázoljuk a feladat során:

data RomanNumeral = I | V | X | L | C | D | M
  deriving (Show, Eq, Ord, Data, Typeable)

type RomanNumber = [RomanNumeral]

Az egyes számjegyei a római számoknak a következő táblázattal értelmezhetőek:

Római szám Arab szám
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

Összetett számok esetén egyszerűen adjuk össze az egyes számjegyek értékeit.

Kompakt alak előállítása (1 pont)

Római számoknak van úgynevezett kompakt és egyszerű alakjuk. A kompakt alaknál például a 4 számot [I,I,I,I] helyett így írjuk: [I,V]. A további szabályokat az alábbi táblázat tartalmazza:

Kompakt alak Egyszerű alak
IV IIII
IX VIIII
XL XXXX
XC LXXXX
CD CCCC
CM DCCCC

Készítsünk egy függvényt, amely egy római számot kompakt alakra hoz!

compact :: [RomanNumeral] -> [RomanNumeral]

Test>
[I, V, I, V, I, V, I, V] :: [RomanNumeral]
Test>
[X, L, V, V, V, I, X] :: [RomanNumeral]
Test>
[C, M, C, X, C] :: [RomanNumeral]

Egyszerű alak előállítása (1 pont)

Készítsünk egy függvényt, amely egy római számot egyszerű alakra hoz! Használjuk a fenti táblázatot!

uncompact :: [RomanNumeral] -> [RomanNumeral]

Test>
[D, C, C, C, C] :: [RomanNumeral]
Test>
[X, X, X, X, V, I, I, I, I] :: [RomanNumeral]
Test>
[M, L, X, X, X, X, I, I, I, I] :: [RomanNumeral]

Római szám konvertálása arab számmá (2 pont)

Készítsük egy függvényt, amely egy római számjegyeket tartalmazó sorozattal ábrázolt római számot arab számmá alakít! (Ne felejtsük el azonban egyszerűsíteni előtte!)

toInt :: [RomanNumeral] -> Int

Test>
0 :: Int
Test>
3 :: Int
Test>
42 :: Int
Test>
1969 :: Int

Arab szám konvertálása római számmá (3 pont)

Készítsünk egy függvényt, amely arab számokat rómaivá tud alakítani! (Illetve az eredményt ne felejtsük el kompakt alakra hozni!)

fromInt :: Int -> [RomanNumeral]

Test>
[I, I, I] :: [RomanNumeral]
Test>
[L, X, X, V, I, I] :: [RomanNumeral]
Test>
[M, C, M, L, X, I, X] :: [RomanNumeral]
Test>
[M, M, M, M, X, C, V, I] :: [RomanNumeral]

Tömörített alak előállítása (2 pont)

Nyilvánvalóan bármely római szám kifejezhető akár pusztán I-k megfelelő hosszú sorozatával, ugyanakkor azért érdemes lenne alkalmazni az összes többi számjegyet is. Ezért készítsünk függvényt, amely egy római számot tömörít az alábbi szabályok segítségével:

Számjegy Kifejtés
V IIIII
X VV
L XXXXX
C LL
D CCCCC

Megjegyzés: A táblázatban található szabályokat csak egyszer kell alkalmazni.

sgroup :: [RomanNumeral] -> [RomanNumeral]

Test>
[D, C, L, X, I, I, I, I] :: [RomanNumeral]
Test>
[V, V, V, I] :: [RomanNumeral]
Test>
[V, V, V, V, V, V, V, V, V, I, I, I, I] :: [RomanNumeral]

Legtömörebb (szabványos) alak előállítása (4 pont)

Írjunk függvényt, amely előállítja egy római szám lehető legtömörebb alakját! Ekkor addig alkalmazzuk a korábbi tömörítési szabályokat (a szám kompakt alakján), amíg csak lehet.

reduce :: [RomanNumeral] -> [RomanNumeral]

Test>
[X, L, I, X] :: [RomanNumeral]
Test>
[M, M, D, L, X, V, I] :: [RomanNumeral]

Pontozás

Ponthatárok: