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


問題はこちら
http://nabetani.sakura.ne.jp/hena/ord22irrpas/

def get_val(board, x, y)
  return [nil, x, y] if board[y][x].nil?
  return [board[y][x], x, y] if board[y][x].class == Fixnum
  return [board[y][x][0], x, y] if board[y][x].size == 3
  [board[board[y][x][1]][board[y][x][0]][0], board[y][x]].flatten
end

def solve(q)
  size, cells = q.split(':')
  x_size, y_size = size.split('x').map(&:to_i)
  board = Array.new(y_size){Array.new(x_size)}
  unless cells.nil?
    cells.split(',').each{|cell|
      x, y, x_sz, y_sz = cell.chars.map(&:to_i)
      board[y][x] = [nil, x_sz, y_sz]
      y_sz.times{|yd|
        x_sz.times{|xd|
          board[y + yd][x + xd] = [x, y] unless xd == 0 and yd == 0
        }
      }
    }
  end

  board[0][0] = 1
  ans = nil
  while(ans.nil?)
    y_size.times{|y|
      x_size.times{|x|
        if board[y][x].nil?
          x_sz = y_sz = 1
        elsif board[y][x].class == Fixnum
          next
        elsif board[y][x].size == 2
          next
        elsif board[y][x][0].nil?
          dummy, x_sz, y_sz = board[y][x]
        else
          next
        end
        done = []
        sum = 0
        if y > 0
          x_sz.times{|xd|
            val, *xy = get_val(board, x + xd, y - 1)
            if val.nil?
              sum = nil
              break
            end
            next if done.include?(xy)
            done << xy
            sum += val
          }
        end
        if x > 0 and !sum.nil?
          y_sz.times{|yd|
            val, *xy = get_val(board, x - 1, y + yd)
            if val.nil?
              sum = nil
              break
            end
            next if done.include?(xy)
            done << xy
            sum += val
          }
        end
        unless sum.nil?
          sum = sum % 100
          if board[y][x].nil?
            board[y][x] = sum
          else
            board[y][x][0] = sum
          end
        end
      }
    }
    ans, *xy = get_val(board, x_size - 1, y_size - 1)
  end
  "%02d"%ans
end

DATA.readlines.each do |line|
  no,q,a,dummy = line.split(/\s+/)
  ans = solve(q)
  print no + "\t" + ans
  puts ans == a ? ' o' : ' x'
end
__END__
11  8x2:3141,5031   07  
0   8x6:6214,3024,5213,5022,0223,7115   32  
1   1x1:    01  
2   2x3:    03  
3   9x7:    03  
4   2x3:0021    03  
5   2x3:1012    03  
6   2x3:0022    02  
7   9x9:1177    98  
8   7x7:2354    02  
9   3x6:1121,0333   12  
10  8x1:4031,0031   01  
11  8x2:3141,5031   07  
12  1x6:0213,0012   01  
13  3x3:1221,0021,0131  04  
14  9x2:1042,8012,6012  18  
15  3x6:0024,0432,2013  03  
16  4x3:1131,0221,2021  10  
17  8x4:3252,2121,6021  48  
18  3x3:2112,0022,0221  03  
19  9x9:1019,3019,5019,7019 25  
20  4x3:3112,0013,1122,2021 04  
21  4x8:1513,2028,0025,0612 04  
22  9x6:2262,5432,8014,3151 39  
23  5x2:2012,3121,3021,0121 06  
24  3x4:1321,1121,1221,0012 05  
25  5x3:0112,1122,4013,0041 09  
26  8x7:3552,3451,5031,0162 95  
27  9x9:2234,8412,0792,6421,1681    52  
28  4x7:0532,1012,3014,3512,2213    60  
29  8x5:4342,3033,0033,6122,1332    08  
30  6x7:1431,3331,1621,2531,4621    36  
31  4x9:1324,3116,0013,2722,2013,0712   67  
32  7x6:3241,4531,1412,0214,3012,5321   54  
33  2x9:1412,0021,0117,0821,1113,1612   05  
34  9x9:2544,6034,1342,6524,0523,4022   99  
35  5x6:0422,4113,2022,2313,4412,2221   20  
36  7x4:6212,0012,6012,2331,3023,0321   10  
37  4x4:3012,1321,2221,0212,0012,1022   11  
38  5x7:1132,1332,0312,4013,0641,4512   77  
39  5x5:0341,3221,3421,0221,1421,0151,1041  54  
40  9x9:6224,5642,0643,0333,3422,1033,4122  36  
41  6x8:0055,1642,5513,0531,5013,5312,0612  12  
42  9x9:4232,1465,7326,3042,1123,7122,0514,7021 34  
43  8x9:0361,5732,6413,0431,7313,1722,2141,3524,7112    22  
44  8x6:6422,1053,6122,1422,3333,6021,0412,0013,6321    22  
45  9x9:3324,5217,8116,2312,7314,6414,3061,7721,1231,1514,3712  17  
46  9x9:7424,4423,0227,3722,4053,2324,5722,2013,7821,6321,2712,6512 39  
47  8x7:5422,6022,2262,1522,3422,0122,0322,2032,6621,4621,0512,7412,5012    06