🏳

ランレングスCarelyちゃんに参戦してみたけど敗北したよ!

2022/12/14に公開

こんにちは〜。

山ときどきエンジニアリング、ところによりクラブ。先週も今週もスノーボードの予定。
本日はエンジニアリング強めの anna@ae__b_ が書く予報でしょう。

🎄🎄この記事は、iCARE Dev Advent Calendar 2022 第1レーン の14日目です。🎄🎄

これはなに

  • 時は遡り12月の頭。TRICKに刺激を受けた弊社VPoEのクドウさんが挑戦状を突きつけてきた
  • その後、おぎじゅんさんべるちぇさんが 弊社のキャラクター Carely ちゃんを愛でていく。
  • 負けず嫌いの私はとりあえず受けて立とうじゃないかと3時間ほど格闘したが敗北。
  • 年末までに余裕があればチャレンジしたい。

そもそもランレングス Carely ちゃんって何よ

  • 前述の方々の記事を読むのが一番理解が進むが、ランレングス符号化を用いて irb でたった1行のコードを叩くと Carely ちゃんが出力されちゃうもの。
  • 勝敗はおそらくだが、バイト数が少なければ少ないほど良いし、コードが美しければ美しいほど良い。
  • ちなみに私の理解
    • クドウさん⇨シンプルなランレングス符号化。986バイトくらいらしい。
    • おぎじゅんさん⇨36進数に変換。767バイトくらいらしい。
    • べるちぇさん⇨Pythonで64bitに変換。656バイトくらいらしい。

私はどういう風に Carely ちゃんを愛でたいんだい?

  • パッと見て、このCarelyちゃんは2進数みたいな見た目をしている
  • だけどおぎじゅんさんがすでに36進数でやってるから、単純な基数変換では勝てない
  • じゃあおぎじゅんさんのコードを改良するならば?
    • Carelyちゃんの1行の中で0または1が36以上連続した場合には2回繰り返す事になる
    • そこは通常のランレングスの方が1文字短い
    • と思って書いてみたけど800バイトくらいになって終わった
  • そもそも人と同じやり方じゃつまんない
  • じゃあ文字列の形式を変えてみるのはどうなんだい?

Ruby メソッドの Array#pack

  • instance method Array#pack
  • バイナリとしてパックするテンプレートを文字列で指定できる
  • ビットストリングでパックしたらなんか良い感じになりそうじゃない?

という訳でCarelyちゃんをパックしてみる

  • これはCarelyちゃんのてっぺんです。

    irb(main):001:0> ["000000000000000000000000000000011000000000000000000000000000000"].pack("b*")
    => "\x00\x00\x00\x80\x01\x00\x00\x00"
    

    おお!!なんか短くなったぞ!!

  • パックしたCarelyちゃんを元に戻してみる

    irb(main):004:0> "\x00\x00\x00\x80\x01\x00\x00\x00".unpack("b*")
    => ["0000000000000000000000000000000110000000000000000000000000000000"]
    

    おかえり!Carelyちゃんのてっぺん!

  • この要領1行ずつ丁寧にCarelyちゃんをパックしていく....

できたものがこちら

irb(main):002:0> ["\x00\x00\x00\x80\x01\x00\x00\x00","\x00\x00\xC0\xFF\xFF\x03\x00\x00","\x00\x00\xFC\xFF\xFF?\x00\x00","\x00\x80\xFF\xFF\xFF\xFF\x01\x00","\x00\xE0\xFF\xFF\xFF\xFF\a\x00","\x00\xF8\xFF\xFF\xFF\xFF\x1F\x00","\x00\xFE\x7F\x00\x00\xFE\x7F\x00","\x80\xFF\x0F\x00\x00\xF0\xFF\x00","\xC0\xFF\x03\x00\x00\xC0\xFF\x03","\xE0\xFF\x00\x00\x00\x00\xFF\a","\xF0?\x00\x00\x00\x00\xFC\x0F","\xF8\x1F\xC0\x01\x80\x03\xF0\x1F","\xF8\x0F\xC0\x03\xC0\x03\x00\x00","\xFC\a\x80\x00\x00\x01\x00\x00","\xFE\x03\x00\x00\x00\x00\x00\x00","\xFE\x03\x00\x00\x00\x00\x00\x00","\xFE\x03\x00\x00\x00\x00\x00\x00","\xFE\x01\xC0\x00\x00\x01\x00\x00","\xFE\x01\x00\a`\x00\x00\x00","\xFE\x01\x00\xF0\a\x00\x00\x00","\xFE\x01\x00\x00\x00\x00\x00\x00","\xFE\x03\x00\x00\x00\x80\x00\x00","\xFE\x03\x00\x00\x00\xFE\x7F\x00","\xFC\a\x00\x00\xC0\xFF\xFF\x01","\xFC\a\x00\x00\xF0\xFF\xFF\a","\xF8\x0F\x00\x00\xF8\xFF\xFF\x0F","\xF8\x1F\x00\x00\xFC\xFF\xFF\x1F","\xF0?\x00\x00\xFC\xFF\xFF?","\xE0\xFF\x00\x00\xFC\xFF\xFF?","\xC0\xFF\x03\x00\xFC\xFF\xFF?","\xC0\xFF\x0F\x00\xFC\xFF\xFF\x1F","\xC0\xFF\xFF\x00\xF8\xFF\xFF\x1F","\xE0\xFF\xFF\xFF\xF0\xFF\xFF\a","\xE0\xFF\xFF\xFF\xC1\xFF\xFF\a","\xF0\xBF\xFF\xFF\a\xFF\xFF\x0F","\xF8\x01\xFC\xFF\x0F\xC0\xC3\x1F","\x18\x00\x80\xFF\x7F\x00\x00\x18","\x00\x00\x00\x00\x00\x00\x00\x00"].each{ |e| p e.unpack("b*")}
["0000000000000000000000000000000110000000000000000000000000000000"]
["0000000000000000000000111111111111111111110000000000000000000000"]
["0000000000000000001111111111111111111111111111000000000000000000"]
["0000000000000001111111111111111111111111111111111000000000000000"]
["0000000000000111111111111111111111111111111111111110000000000000"]
["0000000000011111111111111111111111111111111111111111100000000000"]
["0000000001111111111111100000000000000000011111111111111000000000"]
["0000000111111111111100000000000000000000000011111111111100000000"]
["0000001111111111110000000000000000000000000000111111111111000000"]
["0000011111111111000000000000000000000000000000001111111111100000"]
["0000111111111100000000000000000000000000000000000011111111110000"]
["0001111111111000000000111000000000000001110000000000111111111000"]
["0001111111110000000000111100000000000011110000000000000000000000"]
["0011111111100000000000010000000000000000100000000000000000000000"]
["0111111111000000000000000000000000000000000000000000000000000000"]
["0111111111000000000000000000000000000000000000000000000000000000"]
["0111111111000000000000000000000000000000000000000000000000000000"]
["0111111110000000000000110000000000000000100000000000000000000000"]
["0111111110000000000000001110000000000110000000000000000000000000"]
["0111111110000000000000000000111111100000000000000000000000000000"]
["0111111110000000000000000000000000000000000000000000000000000000"]
["0111111111000000000000000000000000000000000000010000000000000000"]
["0111111111000000000000000000000000000000011111111111111000000000"]
["0011111111100000000000000000000000000011111111111111111110000000"]
["0011111111100000000000000000000000001111111111111111111111100000"]
["0001111111110000000000000000000000011111111111111111111111110000"]
["0001111111111000000000000000000000111111111111111111111111111000"]
["0000111111111100000000000000000000111111111111111111111111111100"]
["0000011111111111000000000000000000111111111111111111111111111100"]
["0000001111111111110000000000000000111111111111111111111111111100"]
["0000001111111111111100000000000000111111111111111111111111111000"]
["0000001111111111111111110000000000011111111111111111111111111000"]
["0000011111111111111111111111111100001111111111111111111111100000"]
["0000011111111111111111111111111110000011111111111111111111100000"]
["0000111111111101111111111111111111100000111111111111111111110000"]
["0001111110000000001111111111111111110000000000111100001111111000"]
["0001100000000000000000011111111111111110000000000000000000011000"]
["0000000000000000000000000000000000000000000000000000000000000000"]
  • パックされたCarelyちゃんは無事戻ってきました。

肝心のバイト数は....?

1316バイトでした。ちーん。パックしてる途中で薄々気付いてた。

リベンジなるか

  • さてここまで辿り着くのに3時間かかった
  • 楽しくなってきたが日付が変わりそうだったので今日はここまで
  • 前述の御三方にはバイト数では負けてしまったがチャレンジ精神は勝利したという事で...

ちょっと待ってよく見てほしいんだ

  • パック後の値をよく見てほしい
"\x00\x00\x00\x80\x01\x00\x00\x00"
"\x00\x00\xC0\xFF\xFF\x03\x00\x00"
"\x00\x00\xFC\xFF\xFF?\x00\x00"
"\x00\x80\xFF\xFF\xFF\xFF\x01\x00"
"\x00\xE0\xFF\xFF\xFF\xFF\a\x00"
"\x00\xF8\xFF\xFF\xFF\xFF\x1F\x00"
"\x00\xFE\x7F\x00\x00\xFE\x7F\x00"
"\x80\xFF\x0F\x00\x00\xF0\xFF\x00"
"\xC0\xFF\x03\x00\x00\xC0\xFF\x03"
"\xE0\xFF\x00\x00\x00\x00\xFF\a"
"\xF0?\x00\x00\x00\x00\xFC\x0F"
"\xF8\x1F\xC0\x01\x80\x03\xF0\x1F"
"\xF8\x0F\xC0\x03\xC0\x03\x00\x00"
"\xFC\a\x80\x00\x00\x01\x00\x00"
"\xFE\x03\x00\x00\x00\x00\x00\x00"
"\xFE\x03\x00\x00\x00\x00\x00\x00"
"\xFE\x03\x00\x00\x00\x00\x00\x00"
"\xFE\x01\xC0\x00\x00\x01\x00\x00"
"\xFE\x01\x00\a`\x00\x00\x00"
"\xFE\x01\x00\xF0\a\x00\x00\x00"
"\xFE\x01\x00\x00\x00\x00\x00\x00"
"\xFE\x03\x00\x00\x00\x80\x00\x00"
"\xFE\x03\x00\x00\x00\xFE\x7F\x00"
"\xFC\a\x00\x00\xC0\xFF\xFF\x01"
"\xFC\a\x00\x00\xF0\xFF\xFF\a"
"\xF8\x0F\x00\x00\xF8\xFF\xFF\x0F"
"\xF8\x1F\x00\x00\xFC\xFF\xFF\x1F"
"\xF0?\x00\x00\xFC\xFF\xFF?"
"\xE0\xFF\x00\x00\xFC\xFF\xFF?"
"\xC0\xFF\x03\x00\xFC\xFF\xFF?"
"\xC0\xFF\x0F\x00\xFC\xFF\xFF\x1F"
"\xC0\xFF\xFF\x00\xF8\xFF\xFF\x1F"
"\xE0\xFF\xFF\xFF\xF0\xFF\xFF\a"
"\xE0\xFF\xFF\xFF\xC1\xFF\xFF\a"
"\xF0\xBF\xFF\xFF\a\xFF\xFF\x0F"
"\xF8\x01\xFC\xFF\x0F\xC0\xC3\x1F"
"\x18\x00\x80\xFF\x7F\x00\x00\x18"
"\x00\x00\x00\x00\x00\x00\x00\x00"
  • \x00とかxFFとか、同じ文字列の繰り返しになってない?
  • ここにランレングス符号化を用いて、\x003とかってやったらめっちゃ短くなるのでは???

おしまい

プログラミングで遊ぶのってたのしーなー。
リベンジするぞ〜。
アドバイスが何かあればぜひ教えてほしいです!

そして弊社 株式会社iCARE では各ポジションのエンジニアを絶賛募集中です〜〜!

Rubyは未経験で入社した私も明日で半年が経ちます!
先輩方や技術顧問の方々にサポートしていただき成長する事ができました...。
Rubyはやった事ないよ〜><という方も興味があればぜひカジュアル面談お待ちしてまーす!

Discussion