第25回オフラインリアルタイムどう書くの問題をRUbyで解く


問題はこちら。
http://nabetani.sakura.ne.jp/hena/ord25rotcell/
会場で解けなかったので、会場でのアドバイスなどを参考にして解きました。

def solve(q)
  last_change = ""
  board = [*"a".."y"].join.scan(/.{5}/).to_a
  q.split(',').each{|e|
    min_y,max_y,min_x,max_x = e.split("").map{|c| board.join.index(c).divmod(5)}.transpose.map(&:minmax).flatten
    locs = []
    cs = []
    if min_y > 0
      x0 = min_x - 1 < 0 ? min_x : min_x - 1
      x0.upto(max_x).each{|x|
        locs << [min_y - 1, x]
        cs << board[min_y - 1][x]
      }
    end
    if max_x + 1 < 5
      y0 = min_y - 1 < 0 ? min_y : min_y - 1
      y0.upto(max_y).each{|y|
        locs << [y, max_x + 1]
        cs << board[y][max_x + 1]
      }
    end
    if max_y + 1 < 5
      x1 = max_x + 1 > 4 ? max_x : max_x + 1
      x1.downto(min_x).each{|x|
        locs << [max_y + 1, x]
        cs << board[max_y + 1][x]
      }
    end
    if min_x > 0
      y1 = max_y + 1 > 4 ? max_y : max_y + 1
      y1.downto(min_y).each{|y|
        locs << [y, min_x - 1]
        cs << board[y][min_x - 1]
      }
    end
    if cs.size == 0
      last_change = "none"
      next
    end
    cs = cs.rotate(-1)
    locs.each_with_index{|loc, i|
      board[loc[0]][loc[1]] = cs[i]
    }
    last_change = cs.sort.join
  }
  last_change
end

DATA.readlines.each do |line|
  no,q,a = line.strip.split(/\s+/)
  ans = solve(q)
  print no + "\t" + ans
  puts ans == a ? ' o' : ' x'
end
__END__
0   ab,gg,uj,pt,an,ir,rr    hpqsvwxy
1   gs,ok   abcdftvwxy
2   gs,sg,ok    none
3   aa,bb,hh,nn hiostwxy
4   ae,ko,uy,cw bdgilnqsvx
5   am,gs,am,gs,am,gs,am,gs cfhkmqrvwx
6   ay  none
7   gs,ay   defjkoptuv
8   bx,ay   none
9   ft,ay   defjkoptuv
10  ab,cd,ef,gh,ij,kl,mn,op,qr,st,uv,wx cdjmnry