「オフラインリアルタイムどう書く第16回(境界線分)」の問題を解いてみた


[横浜へなちょこプログラミング勉強会](https://yhpg.doorkeeper.jp/)にて過去に出題された[境界線分](http://nabetani.sakura.ne.jp/hena/ord16boseg/)を解いてみた。
回答にかかった時間は50分程度。

`LineSegments#count`の中身は初め`cline`と`nline`を`zip`し、1マスずつ比較してから結果を出していたのだが、よくよく考えれば隣り合う行のビットXORを取るだけでよいことに気付いたので書き直した。

```ruby
class LineSegments
  def initialize input
    @field = input.chars.each_slice(2).map{|c| ("%06b" % c.join.to_i(8)).chars.map &:to_i}
  end

  def lines
    count(@field).zip(count(@field.transpose)).map{|r1, r2| r1 + r2}
  end

  private

  def count field
    field.each_cons(2).each_with_object(Array.new(6){0}){|(cline, nline), sum|
      ("%06b" % (cline.join.to_i(2) ^ nline.join.to_i(2))).scan(/1+/){|m| sum[m.size - 1] += 1}
    }
  end
end

test = <<_TEST
/*0*/ test( "060276724276", "6,2,1,1,0,1" );    
/*1*/ test( "770175454177", "2,3,0,3,1,0" );    
/*2*/ test( "743733377170", "9,3,1,0,0,0" );    
/*3*/ test( "724212121273", "5,2,1,1,1,1" );    
/*4*/ test( "100000000000", "3,0,0,0,0,0" );    
/*5*/ test( "000002000000", "4,0,0,0,0,0" );    
/*6*/ test( "003622223600", "0,4,0,4,0,0" );    
/*7*/ test( "520073737070", "8,3,1,1,0,0" );    
/*8*/ test( "770077007700", "0,0,0,0,0,5" );    
/*9*/ test( "555555555514", "2,0,0,0,2,2" );    
/*10*/ test( "764252427600", "4,0,4,0,2,0" );    
/*11*/ test( "774555554177", "3,3,1,3,0,0" );    
/*12*/ test( "674574754557", "11,5,0,1,0,0" );    
/*13*/ test( "000000000000", "0,0,0,0,0,0" );    
/*14*/ test( "777777777777", "0,0,0,0,0,0" );    
/*15*/ test( "774377777577", "6,0,2,0,0,0" );    
/*16*/ test( "070777777777", "0,1,1,0,0,0" );    
/*17*/ test( "373737373737", "0,0,0,0,0,1" );    
/*18*/ test( "603260327725", "30,0,0,0,0,0" );    
/*19*/ test( "466331144663", "30,0,0,0,0,0" );    
/*20*/ test( "000000000242", "3,2,0,0,0,0" );    
/*21*/ test( "567656043772", "18,2,1,0,0,0" );    
/*22*/ test( "200763012420", "15,4,1,0,0,0" );    
/*23*/ test( "400101140052", "14,3,0,0,0,0" );    
/*24*/ test( "764767476476", "13,2,0,1,0,0" );    
/*25*/ test( "001110140110", "12,2,1,0,0,0" );    
/*26*/ test( "765405076527", "16,3,0,1,0,0" );    
/*27*/ test( "377323370373", "8,4,2,0,0,0" );    
/*28*/ test( "250541131216", "11,5,2,0,0,0" );    
/*29*/ test( "744165741476", "12,3,2,0,0,0" );    
/*30*/ test( "042101000300", "10,3,0,0,0,0" );    
/*31*/ test( "002004554101", "11,3,1,0,0,0" );    
/*32*/ test( "371707762706", "15,1,1,0,0,0" );    
/*33*/ test( "130371310175", "7,3,1,2,0,0" );    
/*34*/ test( "212537003613", "13,2,1,1,1,0" );    
/*35*/ test( "157700063411", "15,3,0,0,0,1" );    
/*36*/ test( "011500036007", "6,7,1,0,0,0" );    
/*37*/ test( "743113313517", "17,2,1,0,0,0" );    
/*38*/ test( "174105270405", "13,3,1,1,0,0" );    
/*39*/ test( "427272200311", "13,3,2,0,0,0" );    
/*40*/ test( "725370332237", "12,5,1,1,0,0" );    
/*41*/ test( "005640420046", "12,1,3,0,0,0" );    
/*42*/ test( "700350001101", "14,3,1,0,0,0" );    
/*43*/ test( "577627744076", "16,1,1,1,0,0" );    
/*44*/ test( "620332232007", "10,4,2,1,0,0" );    
/*45*/ test( "260406401000", "15,1,1,0,0,0" );    
/*46*/ test( "737272723276", "5,0,0,0,3,0" );    
/*47*/ test( "000400040444", "7,0,2,0,0,0" );    
/*48*/ test( "370222002177", "13,2,2,0,0,0" );    
/*49*/ test( "372236024656", "9,3,2,0,1,0" );    
/*50*/ test( "276131137003", "11,6,2,0,0,0" );    
/*51*/ test( "742134007240", "13,4,2,0,0,0" );    
/*52*/ test( "777721775571", "13,1,2,0,0,0" );    
/*53*/ test( "700301232233", "11,2,3,0,0,0" );
_TEST

require 'minitest/autorun'

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