第16回オフラインリアルタイムどう書く rubyで解く

会場で 1 時間 + その後 30 分くらいやって解けました

```rb
class LineCounter
  attr_reader :field

  def initialize(input = '')
    @field = build_field(input)
  end

  def count_lines
    [count_h_lines(h_edge_field(@field)), count_h_lines(h_edge_field(@field.transpose))].transpose.map {|(a, b)| a + b }.join(',')
  end

  def h_edge_field(target)
    before = target[0..-2]
    after  = target[1..-1]

    [before, after].transpose.each_with_object([]) do |(b_r, a_r), array|
      array << [b_r, a_r].transpose.each_with_object([]) do |(b, a), ary|
        ary << (([b, a] == [0, 1] || [b, a] == [1, 0]) ? 1 : 0)
      end
    end
  end

  def count_h_lines(target)
    target.inject([0] * 6) do |array, row|
      [count_line(row), array].transpose.map do |a, b|
        a + b
      end
    end
  end

  def count_line(row)
    row.join.split('0').map(&:length).each_with_object([0] * 6) {|i, a| a[i-1] += 1 if i > 0 }
  end

  private

  def build_field(input)
    f = input.each_char.map {|c| '%03d' % c.to_i(8).to_s(2) }.join
    f = f.split('').each_slice(6).to_a
    f.map {|row| row.map(&:to_i) }
  end
end
```

```rb
require 'spec_helper'

describe LineCounter do
  describe '#count_lines' do
    subject { described_class.new(input).count_lines }

    test_data = <<-EOS
    /*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" );
    EOS

    test_data.each_line do |t|
      t =~ /test\( "(\d*)", "(.*)" \)/

      context do
        let(:input) { $1 }
        let(:expectation) { $2 }
        it { should eq expectation }
      end
    end
  end

  describe '#field' do
    subject { described_class.new(input).field }

    context do
      let(:input) { '060276724276' }

      it {
        should eq(
          [[0, 0, 0, 1, 1, 0],
           [0, 0, 0, 0, 1, 0],
           [1, 1, 1, 1, 1, 0],
           [1, 1, 1, 0, 1, 0],
           [1, 0, 0, 0, 1, 0],
           [1, 1, 1, 1, 1, 0]]
        )
      }
    end
  end

  describe '#h_edge_field' do
    subject { described_class.new.h_edge_field(target) }

    context do
      let(:target) {
        [[0, 0, 0, 1, 1, 0],
         [0, 0, 0, 0, 1, 0],
         [1, 1, 1, 1, 1, 0],
         [1, 1, 1, 0, 1, 0],
         [1, 0, 0, 0, 1, 0],
         [1, 1, 1, 1, 1, 0]]
      }

      it {
        should eq(
          [[0, 0, 0, 1, 0, 0],
           [1, 1, 1, 1, 0, 0],
           [0, 0, 0, 1, 0, 0],
           [0, 1, 1, 0, 0, 0],
           [0, 1, 1, 1, 0, 0]]
        )
      }
    end
  end

  describe '#count_h_lines' do
    subject { described_class.new.count_h_lines(target) }

    context do
      let(:target) {
        [[0, 0, 0, 1, 0, 0],
         [1, 1, 1, 1, 0, 0],
         [0, 0, 0, 1, 0, 0],
         [0, 1, 1, 0, 0, 0],
         [0, 1, 1, 1, 0, 0]]
      }

      it { should eq [2, 1, 1, 1, 0, 0] }
    end
  end

  describe '#count_line' do
    subject { described_class.new.count_line(target) }

    context do
      let(:target) { [1, 1, 0, 1, 0, 1] }

      it { should eq [2, 1, 0, 0, 0, 0] }
    end

    context do
      let(:target) { [0, 0, 0, 1, 0, 0] }

      it { should eq [1, 0, 0, 0, 0, 0] }
    end
  end
end
```