「瞬き星」を解いた


第2回 ESM オフラインリアルタイムどう書く( http://d.hatena.ne.jp/E_Mattsan/20151230/1451449205 )の問題
「瞬き星( https://gist.github.com/mattsan/07674b095908fda117a0 )」を解いた。

※ 初出時、問題名を間違えてましたすいません。

良問だと思う。

所要時間 31分。ちょっとくやしい。

で。

私の実装。

M=%w( AJIC CHGE EFJB BIHD DGFA ).map{ |x| "__"+x+"__"}

def try_filp( st, st0, line, ix, dir )
  me=st[line[ix]]
  if me==st0[line[ix+dir*2]]
    st[line[ix+dir]]=me
  elsif me==st0[line[ix+dir*3]]
    st[line[ix+dir]]=me
    st[line[ix+dir*2]]=me
  end
end

def process( st0, pos )
  st=st0.dup
  st[pos]^=1
  M.each do |line|
    ix=line.index(pos)
    next unless ix
    dir = [0,0,1,1,-1,-1][ix]
    try_filp( st, st0, line, ix, dir ) if st[pos] != st[line[ix+dir]]
  end
  st
end

def solve(src)
  st=[*?A..?E].each_with_object({}){|x,o|o[x]=1}
  [*?F..?J].each{|x| st[x]=0}
  src.each_char do |c|
    st=process(st, c)
  end
  [*?A..?J].map{ |x| st[x]==1 ? "W" : "R" }.join
end

DATA.map{ |line|
  src, expected = line.split(/\s+/)
  actual = solve( src )
  ok = actual==expected
  puts( "%s : %s->%s / %s" % [ (ok ? "ok" : "**NG**" ), src, actual, expected ] )
  ok
}.tap{ |x| puts( x.all? ? "all ok" : "something wrong" ) }

__END__
A RWWWWRRRRR
FGHIJABCDE  RRRRRRRRRR

いつも通り、テストデータの大半は省略。

31分経過時点のコードそのまま。
まだリファクタリングしていない。

もっと楽に書けたはずだなぁと、書き上がってから思ったり。
フリップをしていく部分とフリップ前の状態を別に持つ必要があるような気がしていたんだけど、不要だった模様。st0 が無駄。
M の初期化と dir の初期化が汚い感じ。Array にメソッド生やしたほうがよかったか。
グラフのサイズに依存しまくりの try_filp も品がない感じ。