「オフラインリアルタイムどう書く第15回(異星の電光掲示板)」の問題を解いてみた


[横浜へなちょこプログラミング勉強会](https://yhpg.doorkeeper.jp/)にて過去に出題された[異星の電光掲示板](http://nabetani.sakura.ne.jp/hena/ord15elebubo/)を解いてみた。
回答にかかった時間は80分程度と20分オーバー。

空白（点灯のない縦の列）を見て文字の部分を抜き出す部分の実装に非常に時間がかかってしまった。

```ruby
class Board
  PATTERN = {
    "L" => ["10", "11"],
    "R" => ["11", "10"],
    "J" => ["01", "11"],
    "T" => ["111", "010"],
    "U" => ["101", "111"],
    "N" => ["111", "101"],
    "S" => ["011", "110"],
    "Z" => ["110", "011"]
  }

  def initialize input
    @chars = []
    top, bottom = input.split("/").map{|line| "%032b" % line.hex}

    indexes = []
    ("%032b" % (top.to_i(2) ^ bottom.to_i(2))).scan(/11/){ indexes << $~.begin(0) }
    indexes.reverse.each{|i|
      top = top[0..i] + "0" + top[(i+1)..(top.size - 1)]
      bottom = bottom[0..i] + "0" + bottom[(i+1)..(bottom.size - 1)]
    }
    format("%0*b", top.size, top.to_i(2) | bottom.to_i(2)).scan(/1{2,3}/){|char|
      start = $~.begin(0)
      last  = start + (char.size - 1)
      @chars << [top[start..last], bottom[start..last]]
    }
  end

  def chars
    @chars.map{|chr|
      PATTERN.select{|c, pattern| chr === pattern}.keys[0]
    }.join
  end
end

test = <<_TEST
/*0*/ test( "2ed8aeed/34b0ea5b", "LTRSUNTSJ" );    
/*1*/ test( "00000200/00000300", "L" );    
/*2*/ test( "00018000/00010000", "R" );    
/*3*/ test( "00002000/00006000", "J" );    
/*4*/ test( "00000700/00000200", "T" );    
/*5*/ test( "01400000/01c00000", "U" );    
/*6*/ test( "00003800/00002800", "N" );    
/*7*/ test( "000c0000/00180000", "S" );    
/*8*/ test( "00003000/00001800", "Z" );    
/*9*/ test( "132eae6c/1a64eac6", "LRJTUNSZ" );    
/*10*/ test( "637572d0/36572698", "ZSNUTJRL" );    
/*11*/ test( "baddb607/d66b6c05", "LTJZTSSSN" );    
/*12*/ test( "db74cd75/6dac6b57", "ZZZTJZRJNU" );    
/*13*/ test( "3606c2e8/1b0d8358", "ZZSSLTJ" );    
/*14*/ test( "ad98c306/e6cc6183", "UZZZZZZ" );    
/*15*/ test( "4a4aaee3/db6eeaa6", "JJLLUUNNS" );    
/*16*/ test( "ecd9bbb6/598cd124", "TSSZZTTRR" );    
/*17*/ test( "e0000002/40000003", "TL" );    
/*18*/ test( "a0000007/e0000005", "UN" );    
/*19*/ test( "c0000003/80000006", "RS" );    
/*20*/ test( "40000006/c0000003", "JZ" );    
/*21*/ test( "01da94db/00b3b6b2", "TSUJLRSR" );    
/*22*/ test( "76eeaaea/24aaeeae", "TRNNUUNU" );    
/*23*/ test( "1dacaeee/1566e444", "NRJZUTTT" );    
/*24*/ test( "26c9ac60/6c6d66c0", "JSZLRJZS" );    
/*25*/ test( "6c977620/36da5360", "ZZLLTNZJ" );    
/*26*/ test( "069aeae6/0db34eac", "SJSLTUNS" );    
/*27*/ test( "06d53724/049da56c", "RRULRNJJ" );    
/*28*/ test( "069b58b0/04d66da0", "RLRSLZJR" );    
/*29*/ test( "1b6eced4/11b46a9c", "RZZTZNRU" );    
/*30*/ test( "522e8b80/db6ad900", "JLLJNLJT" );    
/*31*/ test( "6546cdd0/376c6898", "ZULSZRTL" );    
/*32*/ test( "4e6d5b70/6ad9d620", "LNSSURST" );    
/*33*/ test( "37367772/65635256", "SNSZNTNJ" );    
/*34*/ test( "25535d58/377669cc", "LUUSLTUZ" );    
/*35*/ test( "0ae6a55d/0eacedcb", "UNSUJUTJ" );    
/*36*/ test( "76762edc/23536a88", "TZNZJNRT" );
_TEST

require 'minitest/autorun'

describe 'EleBoard' do
  test.split("\n").each do |line|
    t, n, input, expect = line.match(/^\/\*(\d+)\*\/\s*test\(\s*"([^"]+)",\s*"([^"]+)"\s*\);\s*$/).to_a
    board = Board.new input
    it input do
      assert_equal expect, board.chars
    end
  end
end
```