IBAN

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

Az IBAN az angol International Bank Account Number (nemzetközi bankszámlaszám) kifejezés rövidítése. Az IBAN országonként eltérő hosszúságú, maximum 34 karakterből áll, azonban hossza egy országon belül azonos. Például: GB29 NWBK 6016 1331 9268 19.

A feladatban ilyen számlaszámok feldolgozását és ellenőrzését fogjuk elvégezni.

Kódcsoport ellenőrzése (1 pont)

Az IBAN értékek kisebb kódcsoportokból épülnek fel, amelyek kizárólag csak számjegyeket ('0' .. '9') és az angol ábécé nagybetűit ('A' .. 'Z') tartalmazhatják, valamint hosszuk nem haladhatja meg a négy karaktert. Kevesebb lehet, de üres nem!

Készítsünk egy függvényt ilyen formátumú kódcsoportok ellenőrzésére!

isValidBlock :: String -> Bool

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

Segédfüggvények (2 pont)

Az IBAN értékekhez országkódok is tartoznak, ennek alapján tudjuk beazonosítani a támogatott országokat, valamint a hozzájuk tartozó pontos hosszat.

Ehhez készítünk egy globális konstanst, amely a számunkra ismert országkódokat tárolja.

type Codes = [(String,Int)]
codes :: Codes
codes = [("GB",22),("GR",27),("SA",24),("CH",21),("IL",23)]

Értelemszerűen további országok is felvehetőek a felsorolásba.

Országkód ellenőrzése


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

Országhoz tartozó hossz lekérdezése

Definiáljunk egy függvényt, amely a szótárból előkeresi az adott String típusú értékhez a neki megfelelő hosszinformációt!

Most már feltétlezhetjük, hogy a keresett kód megtalálható és csak egyszer fordul elő a szótárban.


Test>
22 :: Int
Test>
27 :: Int
Test>
21 :: Int
Test>
23 :: Int

Karakterláncok tömörítése

Adjunk meg egy függvényt, amely eltávolítja a szóközöket a paraméterül kapott karakterláncból!


Test>
"GR1601101250000000012300695" :: String
Test>
"SA0380000000608010167519" :: String

Formai ellenőrzés (2 pont)

A korábbi függvényeink felhasználásával adjunk meg most egy olyat, amely ellenőrzi az IBAN értékekre vonatkozó alapvető formai megszorításokat!

Ezek lényegében a következőek:

Például a következő IBAN megfelel ezeknek a követelményeknek:

GR16 0110 1250 0000 0001 2300 695

A korábbiakból tudjuk, hogy a GR kód (Görögország) létező, 27 karakteres számlaszámokat takar. Valamint a benne szereplő kódcsoportok mindegyik csak a megengedett karaktereket tartalmazza és csak az utolsó tartalmaz kevesebb kódot, mint 4.

Tehát:

isWellFormed :: String -> Bool

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

Az IBAN érvényessége

A formailag megfelelő kódok azonban még nem tekinthetőek helyesnek! Egy IBAN akkor helyes, ha érvényes is. Az érvényességet az alábbi egyszerű algoritmussal lehet ellenőrizni:

  1. Mozgassuk a karakterlánc első 4 karakterét a végére.

    GR1601101250000000012300695 --> 01101250000000012300695GR16
  2. Az alfabetikus (betű) karaktereket alakítsuk kétkarakteres számokká úgy, hogy az A betűtől kezdődően egészen a Z betűig hozzájuk rendelünk egy kétszámjegyű számot: A 10, B 11, , Z 35.

    01101250000000012300695GR16 --> 01101250000000012300695162716
  3. Tekintsük az így keletkező karaktersorozatot egyetlen decimális számként, és számítsuk ki a 97-tel vett maradékát. Ha ez a maradék 1, akkor az IBAN érvényes.

    01101250000000012300695162716 mod 97 --> 1

Tehát a GR16 0110 1250 0000 0001 2300 695 érvényes is.

Kódok feloldása (1 pont)

Valósítsuk meg az ellenőrzés 2. lépését!

resolve :: String -> String

Test>
"123456789" :: String
Test>
"101112131415161718" :: String
Test>
"0123451011121314" :: String
Test>
"0108000000099999999182162" :: String
Test>
"3214282912345698765432161182" :: String

A feloldott kód átalakítása számra (1 pont)

Valósítsuk meg a 3. lépést lehetővé tevő leképezést, vagyis String Integer értékké alakítsát! (A Haskell szerencsére gond nélkül elboldogul ilyen nagy számokkal is.)

Feltételezhetjük, hogy a függvénynek csak nemnegatív számokra kell működnie. A bevezető nullák nem számítanak.

numerize :: String -> Integer

Test>
123456789123456789 :: Integer
Test>
0 :: Integer
Test>
0 :: Integer
Test>
1234 :: Integer

Kód ellenőrzése (2 pont)

Készítsünk egy függvényt, amely a korábbi függvényeink felhasználásával összefoglalja a fentebb ismertetett ellenőrzési folyamatot, és így eldönti egy String értékről, hogy helyes IBAN vagy sem.

isValidIBAN :: String -> Bool

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

IBAN értékek létrehozása (3 pont)

Végül az IBAN típus definícióját így adjuk meg:

data IBAN = IBAN String
 deriving (Eq,Show,Typeable,Data)

Készítsünk egy olyan függvényt, amely egy String értéket IBAN értékké tud alakítani, amennyiben az formailag megfelelő és érvényes. A Maybe típus jelöli, hogy minden más esetben az értéke Nothing.

fromString :: String -> Maybe IBAN

Test>
Just (IBAN "GR1601101250000000012300695") :: Maybe IBAN
Test>
Just (IBAN "GB29NWBK60161331926819") :: Maybe IBAN
Test>
Just (IBAN "SA0380000000608010167519") :: Maybe IBAN
Test>
Just (IBAN "CH9300762011623852957") :: Maybe IBAN
Test>
Just (IBAN "IL620108000000099999999") :: Maybe IBAN
Test>
Nothing :: Maybe IBAN

Megjegyzés. Emlékeztetőül a Maybe típus definíciója:

data Maybe a = Just a | Nothing

Pontozás (elmélet + gyakorlat)