Hamming-kód

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

A feladat során Hamming-kódot fogunk előállítani, amely segítségével ellenőrizni tudjuk, hogy a kommunikáció során nem került-e az adott üzenetbe hiba. A Hamming-kód egy hibajavító kód, azaz ha hiba történt, akkor azt képes bizonyos korlátok közt észlelni, illetve javítani.

A feladat olvashatóságának növelése érdekében bevezetjük az alábbi két típusszinonimát:

type Bit = Int
type BitString = [Bit]

(A type kulcsszó segítségével az Bit típus az Int típus egy másik neve lesz (valójában csak 0 és 1), illetve a BitString típus az Bit típusból alkotott listákat jelenti, hasonlóan a String és [Char] viszonyához. A programban ez semmilyen további megszorítást nem indukál, csupán a beszédesebb függvénytípusok kialakításában segít.)

Szám bitsorozattá konvertálása (1 pont)

Adjuk meg azt a függvényt, amely egy n (0 és 255 közötti) számot alakít bináris számmá!

Megjegyzés: A nagyobb helyiérték előrébb szerepel a listában.

intToBitString :: Int -> BitString

Test>
[1, 0, 0] :: BitString
Test>
[0] :: BitString
Test>
[1, 1, 1, 1, 1, 1, 1] :: BitString
Test>
[1, 0, 1, 1, 0, 1] :: BitString
Test>
⊥₁ :: BitString
⊥₁: toBitString: invalid number 256
CallStack (from HasCallStack):
  error, called at ./HammingCode.lhs:63:41 in main:HammingCode
Test>
⊥₁ :: BitString
⊥₁: toBitString: invalid number -10
CallStack (from HasCallStack):
  error, called at ./HammingCode.lhs:63:41 in main:HammingCode

Bevezetjük a Byte típust, amely 8 Bit-ből áll.

type Byte = [Bit]

Bitsorozat átalakítása bájtá (1 pont)

Definiáljuk azt a függvényt, amely az előző függvényhez hasonlóan, átalakít egy számot bináris formájúvá, de kiegészíti a bináris reprezentációt Byte-tá! Azaz, ha nem 8 hosszúságú a sorozat, akkor bal oldalról kiegészíti azt 0 értékekkel.

intToByte :: Int -> Byte

Test>
[0, 0, 0, 0, 0, 1, 1, 1] :: Byte
Test>
[0, 0, 0, 0, 0, 0, 0, 0] :: Byte
Test>
[1, 0, 0, 0, 0, 0, 0, 0] :: Byte

Elem beszúrása adott pozíciókon (1 pont)

Adjuk meg azt a függvényt, amely egy adott elemet beszúr a lista megfelelő pozícióiba!

Megjegyzés: A pozíciók növekvő sorrendben adottak. Ügyeljünk arra, hogy egy elem beszúrása után a következő elem beszúrását már az előállított listán kell végrehajtani!

FONTOS: A megoldáshoz csak akkor használható fel a későbbiekben szereplő insertElemsAt függvény, ha azt teljes egészében definiáltad (azaz nem hivatkozik az insertElemAt)!

insertElemAt :: a -> [Int] -> [a] -> [a]

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

Sorozatok részei (2 pont)

Adjuk meg azt a függvényt, amely egy kapott n (0-nál nagyobb szám) szám felhasználásával a lista azon részét adja vissza, amely a következő lépésekkel állítható elő:

  1. a részsorozatot a lista n-edik pozíciójától kezdi előállítani (ne feledjük, hogy a lista indexelése 0-tól kezdődik), azaz elhagy n − 1 darab elemet a lista elejéről,

  2. vesz n darab elemet a listából, majd ugyanennyit elhagy,

  3. addig ismétli az előző pontot, amíg a lista el nem fogy.

p :: Int -> [a] -> [a]

Test>
[1, 3, 5, 7] :: [Integer]
Test>
[2, 3, 6, 7] :: [Integer]
Test>
⊥₁ :: [Integer]
⊥₁: p: invalid number 0
CallStack (from HasCallStack):
  error, called at ./HammingCode.lhs:133:20 in main:HammingCode
Test>
⊥₁ :: [()]
⊥₁: p: invalid number -1
CallStack (from HasCallStack):
  error, called at ./HammingCode.lhs:133:20 in main:HammingCode

Bitsorozat paritása (1 pont)

Definiáljuk a parity nevű függvényt, amely 1-et ad vissza, ha a listában páratlan számú 1-es van, egyébként pedig 0-t.

parity :: BitString -> Bit

Test>
1 :: Bit
Test>
0 :: Bit
Test>
0 :: Bit

Elemek beszúrása adott pozíciókon (1 pont)

Korábban definiáltuk az insertAt függvényt, amely egy adott elemet szúrt be megadott pozíciókba. Általánosítsuk ezt a függvényt olyan módon, hogy sorban megadhassuk melyik pozícióra milyen elemet szeretnénk beszúrni!

insertElemsAt :: [(a, Int)] -> [a] -> [a]

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

Hamming kód előállítása (3 pont)

Definiáljuk a hamming függvényt, amely egy bájtot kiegészít ellenőrzőbitekkel, ami a későbbiekben felhasználható a kód hibamentességének ellenőrzéséhez!

Az ellenőrző biteket a listába a 2 hatványainak megfelelő pozíciókra kell beszúrni, azaz egy bájt esetén ezek 1, 2, 4, 8. (Ne feledjük, hogy a lista indexelése 0-től kezdődik!)

Az algoritmus a következő:

  1. hogy meg tudjuk állapítani az ellenőrző bitek értékét, kezdetben helyettesítsünk a nekik megfelelő pozíciókon 0 értéket a listába,

  2. adjuk meg ezek részsorozatait a p függvény segítségével (n értéke rendre 1,2,4,8 lesz),

  3. határozzuk meg a részsorozatok paritását,

  4. a paritásnak megfelelően helyettesítsük a megfelelő pozíciókba a paritás bitet. Tehát, ha az eredeti sorozatunk a1, a2, a3, a4, a5, a6, a7, a8, az ennek megfelelő hamming kód p1, p2, a1, p4, a2, a3, a4, p8, a5, a6, a7, a8

Megjegyzés: pi a p i függvénynek megfelelő paritás bit.

hamming :: Int-> BitString

Test>
[0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0] :: BitString
Test>
[1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1] :: BitString
Test>
[0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0] :: BitString
Test>
[0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1] :: BitString

Hamming kód validálása (1 pont)

Adjuk meg a hamming kódot ellenőrző függvényt, amely a kapott bitsorozatról (feltehetjük, hogy ez egy bájt kódolásával jött létre) eldönti, hogy tartalmaz-e hibát!

Megjegyzés: A kód akkor tartalmaz hibát, ha valamelyik p1, p2, p4, p8 sorozat paritása nem 0.

validate :: BitString -> Bool

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

Hiba megkeresése (1 pont)

Definiáljuk azt a függvényt, amely meghatározza a hibás bit pozícióját! A pozíció meghatározása az alábbiak szerint történik:

Megjegyzés: A függvény nullát adjon vissza, ha a bitsorozatban nincs hiba!

findErrorPosition :: BitString -> Int

Test>
11 :: Int
Test>
1 :: Int
Test>
0 :: Int

Hiba javítása (2 pont)

Adjuk meg azt a függvényt, amely javítja a hibát abban az esetben, ha ez szükséges/lehetséges! Azaz lecseréli a hibás bitet.

correctError :: BitString -> BitString

Test>
[0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1] :: BitString
Test>
⊥₁ :: BitString
⊥₁: correctError: more than one error in code
CallStack (from HasCallStack):
  error, called at ./HammingCode.lhs:260:20 in main:HammingCode

Pontozás