Ruby Quiz - Challenge #8 - Base32 Alphabet - Convert the Super "Sekretoooo" 240-Bit CryptoKitties Genome to Kai Notation - Annipurrsary!

Gerald Bauer <[email protected]>
Newsgroups gmane.comp.lang.ruby.general
Message-ID <CAAxEZd9RbRVSObbTYt_wixeMLm15qtEg16jdYmnBZm-acE-ydA@mail.gmail.com>
Hello,

  It's Friday. Ruby Quiz time! Join us. Let's keep going with a new
Ruby Quiz [1] every Friday. Here we go:

Challenge #8 - Base32 Alphabet - Convert the Super "Sekretoooo"
240-Bit CryptoKitties Genome to Kai Notation - Annipurrsary!

Annipurrsary! Let's celebrate one year of CryptoKitties -
yes, more than one million cute little cartoon cats on the blockchain.

Let's convert the super "sekretoooo" kitty genome - that is, a 240-bit
integer number
where every 5-bit block is a gene - into the base32 (2^5=32) kai notation.


Q: What's base32 kai notation?

Kai notation (named to honor [Kai
Turner](https://medium.com/@kaigani/the-cryptokitties-genome-project-on-dominance-inheritance-and-mutation-b73059dcd0a4)
who deciphered the kitties genome)
is a base58 variant / subset for decoding the 240-bit integer into 5-bit blocks.
Each 5-bit block is a gene with 32 possible traits.
The 240-bit genome breaks down into 12 groups of 4 (x 5-bit) genes
(that is, 12 x 4 x 5-bit = 240 bits)
Example:

|Kai    |Binary |Num|Kai    |Binary |Num|Kai    |Binary |Num|Kai
|Binary |Num|
|-------|-------|---|-------|-------|---|-------|-------|---|-------|-------|---|
| **1** | 00000 | 00 | **9** | 01000 | 08 | **h** | 10000 |16 | **q**
| 11000 |24 |
| **2** | 00001 | 01 | **a** | 01001 | 09 | **i** | 10001 |17 | **r**
| 11001 |25 |
| **3** | 00010 | 02 | **b** | 01010 | 10 | **j** | 10010 |18 | **s**
| 11010 |26 |
| **4** | 00011 | 03 | **c** | 01011 | 11 | **k** | 10011 |19 | **t**
| 11011 |27 |
| **5** | 00100 | 04 | **d** | 01100 | 12 | **m** | 10100 |20 | **u**
| 11100 |28 |
| **6** | 00101 | 05 | **e** | 01101 | 13 | **n** | 10101 |21 | **v**
| 11101 |29 |
| **7** | 00110 | 06 | **f** | 01110 | 14 | **o** | 10110 |22 | **w**
| 11110 |30 |
| **8** | 00111 | 07 | **g** | 01111 | 15 | **p** | 10111 |23 | **x**
| 11111 |31 |

Note: The digit-0 and the letter-l are NOT used in kai.

> Base58 is a group of binary-to-text encoding schemes used to represent large integers as alphanumeric text.
> It is similar to Base64 but has been modified to avoid both non-alphanumeric characters
> and letters which might look ambiguous when printed [e.g. 1 and l, 0 and o].
> It is therefore designed for human users who manually enter the data,
> copying from some visual source, but also allows easy copy
> and paste because a double-click will usually select the whole string.
>
> [-- Base58 @ Wikipedia](https://en.wikipedia.org/wiki/Base58)


Let's get coding, for an example:

```

# A 240-bit super "sekretoooo" integer genome

# hexadecimal (base 16)
genome = 0x4a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce
# decimal (base 10)
genome = 512955438081049600613224346938352058409509756310147795204209859701881294
# binary (base 2)
genome = 0b010010100101001010010011000111001110010000001000010111000001010010111101110011100000000101001010000000110001100010000100\
           011010100000110010000000100011000110000000101001010010100110001100010100101000110100101000010010100101011011100111001110
```


Let's convert from decimal (base 10) to hexadecimal (base 16 - 2^4)
and binary (base 2 that is, 0 and 1):


```
p genome    # printed as decimal (base 10) by default
# => 512955438081049600613224346938352058409509756310147795204209859701881294

p genome.to_s(16)
# => "4a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce"

p genome.to_s(2)
# => "10010100101001010010011000111001110010000001000010111000001010010111101110011100000000101001010000000110001100010000100\
#     011010100000110010000000100011000110000000101001010010100110001100010100101000110100101000010010100101011011100111001110"

bin = '%0240b' % genome     # note: adds leading zeros - to_s(2) does not
p bin.size
# => 240
p bin
# => "010010100101001010010011000111001110010000001000010111000001010010111101110011100000000101001010000000110001100010000100\
#     011010100000110010000000100011000110000000101001010010100110001100010100101000110100101000010010100101011011100111001110"

hex = '%060x' % genome     # note: adds leading zeros - to_s(16) does not
p hex.size
# => 60
p hex
# => 60
# => "4a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce"
```

And finally:

```
kai = kai_encode( genome )   ## number to base32 kai notation
p kai
# => "aaaa788522f2agff16617755e979244166677664a9aacfff"
```



The challenge: Code a `kai_encode` method that passes the RubyQuizTest :-) [2].

```
def kai_encode( num )
  # ...
end
```

For the starter level 1 turn
super "sekretoooo" kitty genome 240-bit integer numbers
into base 32 (2^5) kai notation.

For the bonus level 2 pretty print and format
the base 32 (2^5) kai notation in groups of four e.g.
turn:

    "aaaa788522f2agff16617755e979244166677664a9aacfff"

into

    "aaaa 7885 22f2 agff 1661 7755 e979 2441 6667 7664 a9aa cfff"


```
def kai_fmt( kai )
  # ...
end
```


Start from scratch or, yes, use any library / gem you can find.

To qualify for solving the code challenge / puzzle you must pass the test:

```
require 'minitest/autorun'

class RubyQuizTest < MiniTest::Test

  ################################
  # test data
  def genomes
     [
       [0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce,
        "aaaa 7885 22f2 agff 1661 7755 e979 2441 6667 7664 a9aa cfff"]
     ]
  end

  #############
  # tests
  def test_kai_encode
    genomes.each do |pair|
      num       = pair[0]
      exp_value = pair[1].gsub(' ','')   # note: remove spaces

      assert_equal exp_value, kai_encode( num )
    end
  end # method test_kai_encode

  def test_kai_fmt
    genomes.each do |pair|
      kai       = pair[1].gsub(' ','') # remove spaces
      exp_value = pair[1]

      assert_equal exp_value, kai_fmt( kai )
    end
  end # method test_kai_fmt

end # class RubyQuizTest
```


Post your code snippets on the "official" Ruby Quiz Channel,
that is, the ruby-talk mailing list right here.

Happy data wrangling and genome genetics bits & bytes slicing with Ruby.


[1] https://github.com/planetruby/quiz/tree/master/008
[2] https://github.com/planetruby/quiz/blob/master/008/test.rb

Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.