Re: Ruby Quiz - Challenge #8 - Base32 Alphabet - Convert the Super "Sekretoooo" 240-Bit CryptoKitties Genome to Kai Notation - Annipurrsary!
Delton Ding <[email protected]>
| Newsgroups | gmane.comp.lang.ruby.general |
|---|---|
| Message-ID | <[email protected]> |
One-line solution with Ruby:
def kai_encode(num)
num.to_s(2).rjust(240, '0').scan(/.{5}/).map {|n|
'123456789abcdefghijklmnopqrstuvwx'[n.to_i(2)]}.join
end
def kai_fmt(kai)
kai.scan(/.{4}/).join(' ')
end
kai_encode(0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce)
# => "aaaa788522f2agff16617755e979244166677664a9aacfff"
kai_fmt(kai_encode(0x00004a52931ce4085c14bdce014a0318846a0c808c60294a6314a34a1295b9ce))
# => "aaaa 7885 22f2 agff 1661 7755 e979 2441 6667 7664 a9aa cfff"
On 2018/12/08 1:01 AM, Gerald Bauer wrote:
> 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>
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>
signature.asc
(application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEE3CRLRKMee5f4BJxLCpUbdHuLEawFAlwKobUACgkQCpUbdHuL EawL9A/9EuAjzHGj5ImFka0dG7tjJTevMJ1vORCI1UHanAwoMviH7hU8iHBOfVZb W7eW0AK8k6+RdxeC+ugZpWOZa6a1YN/e0dqUbvDkYVxdb0OYaloN/IsATE9aHYbv 5kDbyCDQcqyauZvLhsPMgIArldwBzOPWq9r/DQMr3VnwAs5ok2/p+WnSDBl1OmES xpWde+xjOrk0BUzUfyRDMI1bYVMZGzw0Jjf0eTreOAV2XalLmXr1oEYQYStHwoa9 Zb7xKR0Nf0RxWsDVXNEuXunG6AZ+HFlgsbA2/CHEhHnjbsA3meeYm94JXBhcfgxf GBKh3Vqq1DLlBzVed+fSNUDZUeFaskGXIh969+kwIJsQB1Naifc+zioo1/7hvccO 3o6zkUdEGL29V/HyHSQKk22MI4KoEVB6WfkMM+j+1Dk/LzAJqDC/XuCiqDFN/t1W Xy+KtakOzKnBbWOvRHLOAn2i925eVR2LhZ0jljVNivP4BGVdiWY0JfDJ0hfw57eA gVSYmPY/j0XM1DN/bYd0J027VkMpAutmwRxcgQJgGDSMgBXTonbU0ndRH/fkKgP3 aPGrUqhQhgmGaM6xPtuBcVNoACOxoznRpjkr6Rl0rnWw7hZBCVg+tLdo3M6xJGEw i3T3F6Hha87c4r7Yox/CRD5s73AsKkfjdaXYRWjtO7s/m9bOY3I= =tiVF -----END PGP SIGNATURE-----