Amikor rekurzióval haladunk végig felsorolhatókon (listák, bitsztringek, stringek), gyakran két dologra kell figyelnünk:
Ezek kezelésére használhatunk egy akkumulátort.
Az akkumulátor egy változó, amelyet az adatok mellett adunk át. Arra szolgál, hogy a függvény végrehajtásának aktuális állapotát hívásról hívásra továbbadja, amíg el nem érünk az alapesetig. Az alapesetben az akkumulátor szolgál a rekurzív függvényhívás végső értékének visszaadására.
Az akkumulátor kezdőértékét a függvény szerzőjének kell megadnia, nem a függvény felhasználójának. Ehhez két függvényt kell definiálnunk: egy nyilvános függvényt, amely csak a szükséges adatokat kapja argumentumként, és beállítja a kezdőértéket, valamint egy privát függvényt, amely az akkumulátort is megkapja. Elixirben gyakori minta, hogy a privát függvény nevét do_ előtaggal látjuk el.
# Count the length of a list without an accumulator
def count([]), do: 0
def count([_head | tail]), do: 1 + count(tail)
# Count the length of a list with an accumulator
def count(list), do: do_count(list, 0)
defp do_count([], count), do: count
defp do_count([_head | tail], count), do: do_count(tail, count + 1)
Az akkumulátor használatával a rekurzív függvényeket farokrekurzív függvényekké alakíthatjuk. Egy függvény akkor farokrekurzív, ha a benne utolsóként végrehajtott művelet a saját magára irányuló hívás.
A DNS-kutatólaborodban már többféle módszert is kipróbáltál a kutatási adataid tömörítésére, hogy tárhelyet takaríts meg. Az egyik csapattársad azt javasolja, hogy alakítsd a DNS-adatokat bináris ábrázolássá:
| Nukleinsav | Kód |
|---|---|
| szóköz | 0000 |
| A | 0001 |
| C | 0010 |
| G | 0100 |
| T | 1000 |
Elgondolkodsz rajta, hiszen ez akár a felére is csökkentheti a szükséges adattárolási költségeket, igaz, az emberi olvashatóság rovására. Úgy döntesz, hogy írsz egy modult az adataid kódolásához és dekódolásához, hogy felmérd a megtakarítást.
Valósítsd meg az encode_nucleotide/1 függvényt, amely átveszi a nukleinsav kódpontját, és visszaadja a kódolt kód egész értékét.
DNA.encode_nucleotide(?A)
# => 1
# (which is equal to 0b0001)
Valósítsd meg a decode_nucleotide/1 függvényt, amely átveszi a kódolt kód egész értékét, és visszaadja a nukleinsav kódpontját.
DNA.decode_nucleotide(0b0001)
# => 65
# (which is equal to ?A)
Valósítsd meg az encode/1 függvényt, amely átvesz egy nukleinsavakat és hézagokat ábrázoló charlistet, és visszaadja a kódolt adatok bitstringjét.
DNA.encode(~c"AC GT")
# => <<18, 4, 8::size(4)>>
Valósítsd meg a decode/1 függvényt, amely átvesz egy nukleinsavakat és hézagokat ábrázoló bitstringet, és a dekódolt adatokat charlistként adja vissza.
DNA.decode(<<132, 2, 1::size(4)>>)
# => ~c"TG CA"
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.