A bináris adatokkal való munka minden nyelvben fontos fogalom, és az Elixir elegáns szintaxist kínál a bináris adatok írásához, illesztéséhez és felépítéséhez.
Az Elixirben a bináris adatokat bitstring típusnak nevezik. A bináris adat típusa (amit nem szabad összekeverni a bináris adatokkal általában) a bitstring egy speciális formája, amelyről egy későbbi feladatban lesz szó.
A bitstring literálokat a <<>> speciális formával definiáljuk. Amikor egy bitstring literált definiálunk, az szegmensekben épül fel. Minden szegmensnek van értéke és típusa, amelyeket a :: operátor választ el egymástól. A típus határozza meg, hogy hány bitet használunk az érték kódolására. A típus teljesen elhagyható, ilyenkor alapértelmezés szerint egy 8 bites egész értéket kapunk.
# This defines a bitstring with three segments of a single bit each
<<0::1, 1::1, 0::1>>
A ::1 típus megadása rövidítése a ::size(1) írásmódnak. Ha a bitméret egy változóból származik, a hosszabb szintaxist kell használnod.
Amikor bináris egész literálokat írunk, közvetlenül 2-es alapú jelöléssel is leírhatjuk őket, ha a literál elé 0b-t teszünk. Ne feledd, hogy ezek ettől függetlenül tízes számrendszerbeli számként jelennek meg, amikor a tesztek eredményében vagy az iexben kiíródnak.
<<0b1011::4>> == <<11::4>>
# => true
Ha a szegmens értéke meghaladja a szegmens típusának kapacitását, akkor az érték balról csonkolódik.
<<0b1011::3>> == <<0b0011::3>>
# => true
A speciális formával egy meglévő bitstring elé és mögé is fűzhetsz. Ha a meglévő bitstring mérete ismeretlen, akkor a ::bitstring típust kell használnod rajta.
value = <<0b110::3, 0b001::3>>
new_value = <<0b011::3, value::bitstring, 0b000::3>>
# => <<120, 8::size(4)>>
A speciális formával összefűzhetjük a változókban tárolt bitstringeket. Két ismeretlen méretű bitstring összefűzésekor a ::bitstring típust kell használni.
first = <<0b110::3>>
second = <<0b001::3>>
concatenated = <<first::bitstring, second::bitstring>>
# => <<49::size(6)>>
A speciális formából mintaillesztéssel is kinyerhetsz értékeket. Minden egyes kimenteni kívánt darabhoz tudnod kell a bitek számát, egyetlen kivétellel: a ::bitstring típus használható ismeretlen méretű bitstringre való mintaillesztésre, de ez csak az utolsó darabnál alkalmazható.
<<value::4, rest::bitstring>> = <<0b01101001::8>>
value == 0b0110
# => true
A bitstringek a létrehozásukhoz használt formátumtól eltérő formátumban is megjelenhetnek (a tesztfuttató vagy az iex által kiírva). Ez gyakran zavart okoz, amikor az ember éppen a bitstringeket tanulja.
Alapértelmezés szerint a bitstringek 8 bites (egy byte-os) darabokban jelennek meg, még akkor is, ha más méretű darabokkal hoztad létre őket.
<<2011::11>>
# => <<251, 3::size(3)>>
Ha olyan bitstringet hozol létre, amely egy nyomtatható UTF-8 kódolású stringet reprezentál, az stringként jelenik meg.
<<>>
# => ""
<<65, 66, 67>>
# => "ABC"
A számfestés (más néven színezés számok alapján) olyan fekete-fehér képek, amelyeket színezésre szántak. A kép különböző területeit különböző számok jelölik, a számok egy előre meghatározott színpaletta adott színeinek felelnek meg. A cél, hogy a területeket a megfelelő színekkel töltsd ki, és a végén egy gyönyörű, színes kép táruljon fel. Ez egy pihentető tevékenység gyerekeknek és felnőtteknek egyaránt.
Az a feladatod, hogy írj egy számfestő alkalmazást Elixirben. Azt szeretnéd, hogy az alkalmazásod egy egyedi adatformátumban tudjon képeket importálni és exportálni. Úgy döntöttél, hogy bináris fájlokban tárolod a képeid adatait.
Ez a feladat feltételezi, hogy ismered a bináris számokat, és érted, milyen elvek alapján lehet a bináris számokat tízes számrendszerbeli számokká és a tízes számrendszerbeli számokat bináris számokká alakítani.
Képzeljük el, hogy van egy képed egy mosolygó arcról, mint amilyen lentebb látható. A kép háttere fehér. A mosolygó arcnak fekete a körvonala, és sárga a kitöltő színe.
Ez a kép 3 színt használ. Rendeljünk indexeket ezekhez a színekhez:
0 (bináris: 0b00) a fehérhez,1 (bináris: 0b01) a feketéhez,2 (bináris: 0b10) a sárgához.Ezekkel a színindexekkel most már ábrázolhatjuk az egyes pixelek színét.
| Mosolygó arc | Mosolygó arc színindexekkel |
|---|---|
![]() |
![]() |
Valósítsd meg a PaintByNumber.palette_bit_size/1 függvényt. A palettában lévő színek számát kapja meg, és adja vissza, hogy hány bitre van szükség ennyi színindex bináris számként való ábrázolásához. A színindexek mindig 0-tól kezdődnek, és folytonos, növekvő egész számok.
Például 13 különböző szín ábrázolásához 4 bitre van szükség. 4 biten legfeljebb 16 színindex tárolható (2^4). 3 bit nem lenne elég, mert 3 biten csak legfeljebb 8 színindex tárolható (2^3).
PaintByNumber.palette_bit_size(13)
# => 4
Megjegyzés: az Elixir standard könyvtárában nincs log2 függvény. Később megtanulod, hogyan használhatod az Erlang-könyvtárakat Elixirből, ahol megtalálod ezt a függvényt. Most viszont rekurzióval és a hatványoperátorral ** oldd meg ezt a feladatot.
Valósítsd meg a PaintByNumber.empty_picture/0 függvényt. Egy üres bitstringgel kell visszatérnie.
Az alkalmazásod alapfunkcióinak manuális teszteléséhez egy előre meghatározott tesztképet fogunk használni. A tesztkép 4 pixelből áll, 4 különböző színnel.
Valósítsd meg a PaintByNumber.test_picture/0 függvényt. Egy 4 szegmensből álló bitstringgel kell visszatérnie.
Minden szegmens bitmérete 2 legyen. A szegmensek értéke 0, 1, 2 és 3 legyen.
Valósítsd meg a PaintByNumber.prepend_pixel/3 függvényt. Három argumentumot kap: egy bitstringet azzal a képpel, amelynek az elejére fűzünk, a paletta színeinek számát, valamint az új pixel színének indexét. Egy bitstringgel kell visszatérnie, amely azt a képet tartalmazza, amelynek az elejére hozzáadtuk az új pixelt.
picture = <<2::4, 0::4>>
color_count = 13
pixel_color_index = 11
PaintByNumber.prepend_pixel(picture, color_count, pixel_color_index)
# => <<178, 0::size(4)>>
# (which is equal to <<11::4, 2::4, 0::4>>)
Valósítsd meg a PaintByNumber.get_first_pixel/2 függvényt. Két argumentumot kap: egy bitstringet azzal a képpel, amelyből olvasunk, és a paletta színeinek számát. A megadott kép első pixelének színindexével kell visszatérnie. Üres kép esetén nil-t kell visszaadnia.
picture = <<19::5, 2::5, 18::5>>
color_count = 20
PaintByNumber.get_first_pixel(picture, color_count)
# => 19
Valósítsd meg a PaintByNumber.drop_first_pixel/2 függvényt. Két argumentumot kap: egy bitstringet azzal a képpel, amelyből eltávolítunk egy pixelt, és a paletta színeinek számát. A képpel kell visszatérnie, de az első pixel nélkül. Üres kép esetén üres képpel kell visszaadnia.
picture = <<2::3, 5::3, 5::3, 0::3>>
color_count = 6
PaintByNumber.drop_first_pixel(picture, color_count)
# => <<180, 0::size(1)>>
# (which is equal to <<5::3, 5::3, 0::3>>)
Valósítsd meg a PaintByNumber.concat_pictures/2 függvényt. Két argumentumot kap, két bitstringet. Azzal a bitstringgel kell visszatérnie, amely az első argumentumnak a második elé fűzésének eredménye.
picture1 = <<52::6, 51::6>>
picture2 = <<0::6, 34::6, 12::6>>
PaintByNumber.concat_pictures(picture1, picture2)
# => <<211, 48, 34, 12::size(6)>>
# (which is equal to <<52::6, 51::6, 0::6, 34::6, 12::6>>)
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Elixir nyelvet 58 fogalom168 feladat segítségével, valódi emberi mentorálással, mindez ingyen.