LoginSignup
0
0

More than 5 years have passed since last update.

テトロミノビンゴをRubyで解く

Posted at

問題はこちら
http://nabetani.sakura.ne.jp/codeiq/tetromino_bingo/

require 'open-uri'
DATA_URI = 'http://nabetani.sakura.ne.jp/codeiq/tetromino_bingo/data.txt'

def find_num_pos(num, board)
  board.each_with_index{|row, y|
    row.each_with_index{|cell, x|
      return [y, x] if cell == num
    }
  }
  nil
end

def check_tetro(board, holes)
  holes_cur = holes
  holes_new = nil
  holes_next = holes 
  begin
    holes_new = holes_next
    holes_next = []
    holes_new.each {|y, x|
      [[1,0],[0,1],[-1,0],[0,-1]].each {|dy, dx|
        ny, nx = y + dy, x + dx
        next unless board[ny][nx].nil?
        nyx = [ny, nx]
        next if holes_cur.include?(nyx)
        next if holes_next.include?(nyx)
        holes_next << nyx
      }
    }
    holes_cur += holes_next
  end while(!holes_next.empty?)
  holes_cur.size == 4 ? holes_cur : nil
end

def adjust_pos(holes)
  y_min = holes.map(&:first).min
  x_min = holes.map(&:last).min
  holes.map{|y, x| [y - y_min, x - x_min]}.sort
end

def rotate(holes)
  adjust_pos(holes.map{|y, x| [-x, y]})
end

def judge_tetro_char(holes)
  tetros = {
    [[0,0],[1,0],[2,0],[3,0]] => 'I',
    [[0,0],[1,0],[2,0],[2,1]] => 'L',
    [[0,0],[0,1],[1,0],[1,1]] => 'O',
    [[0,0],[1,0],[1,1],[2,1]] => 'S',
    [[0,0],[1,0],[1,1],[2,0]] => 'T',
  }
  mirror_holes = holes.map{|y, x| [-y, x]}
  4.times{
    holes = rotate(holes)
    return tetros[holes] if tetros[holes]
    mirror_holes = rotate(mirror_holes)
    return tetros[mirror_holes] if tetros[mirror_holes]
  }
  "-"
end

def solve(nums, q)
  board = [[0]*7] + q.split('/').map{|e| [0] + e.split(',').map(&:to_i) + [0]} + [[0]*7]

  nums.each{|num|
    y, x = find_num_pos(num, board)
    if x
      board[y][x] = nil
      holes = check_tetro(board, [[y, x]])
      return judge_tetro_char(holes) if holes
    end
  }
  "-"
end

#header, *data = DATA.readlines
header, *data = open(DATA_URI).readlines

nums = header.chop.split(',').map(&:to_i)
sums = Hash.new(0)
data.each_with_index do |line, i|
  q,a = line.chop.split(/\s+/)
  ans = solve(nums, q)
  if a
    print i.to_s + "\t" + ans
    puts ans == a ? ' o' : ' x'
  end
  sums[ans] += 1 unless ans == '-'
end
p sums
__END__
74,72,90,23,68,36,35,41,67,18,1,89,39,80,47,10,45,40,26,91,6,98,73,53,44,24,52,63,46,59,28,92,13,94,66,49,3,87,64,4,88,76,96,9,29,85,42,82,25,51,86,19,83,14,77,78,58,62,81,22,93,15,2,20,33,57,37,48,38,34,79,17,65,60,11,31,27,5,69,32,95,99,50,16,70,75,12,7,56,21,97,30,8,61,55,84,54,71,43
93,84,33,81,79/18,36,13,89,92/46,34,55,78,63/32,59,49,88,11/3,45,60,56,20   S
74,72,90,23,68/36,35,41,67,18/1,89,39,80,47/10,45,40,26,91/6,98,73,53,44    I
11,31,69,27,5/32,95,99,50,43/16,70,75,84,30/12,7,56,54,8/21,97,71,61,55 L
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0