class Game attr_reader :board def initialize(game_board) @board = game_board sq1 = [0,1,2,9,10,11,18,19,20] sq2 = [3,4,5,12,13,14,21,22,23] sq3 = [6,7,8,15,16,17,24,25,26] sq4 = [27,28,29,36,37,38,45,46,47] sq5 = [30,31,32,39,40,41,48,49,50] sq6 = [33,34,35,42,43,44,51,52,53] sq7 = [54,55,56,63,64,65,72,73,74] sq8 = [57,58,59,66,67,68,75,76,77] sq9 = [60,61,62,69,70,71,78,79,80] @squares = [sq1,sq2,sq3,sq4,sq5,sq6,sq7,sq8,sq9] @all_vals = Array.new(9) {|i| i+1} end def get_poss_col_vals(cell_index) col_cells = get_col_for_cell(cell_index) used_vals = col_cells.collect{|i| @board[i]} return @all_vals - used_vals end def get_poss_sqr_vals(cell_index) square = get_square_for_cell(cell_index) used_vals = square.collect{|i| @board[i]} return @all_vals - used_vals end def get_poss_row_vals(cell_index) row_cells = get_row_for_cell(cell_index) used_vals = row_cells.collect{|i| @board[i]} return @all_vals - used_vals end def get_pv_for_sqr(cell_index) square = get_square_for_cell(cell_index) return get_possible_values(cell_index, square) end def get_pv_for_row(cell_index) row_cells = get_row_for_cell(cell_index) return get_possible_values(cell_index, row_cells) end def get_pv_for_col(cell_index) col_cells = get_col_for_cell(cell_index) return get_possible_values(cell_index, col_cells) end def get_square(sq) @squares[sq-1].collect{|i|@board[i]} end def solve 100.times do |i| @board.each_index do |cell_index| if @board[cell_index] == 0 solve_cell(cell_index) end end end end def is_solved? return !@board.member?(0) end private def get_possible_values_for_cell(cell_index) sqr_pv = get_poss_sqr_vals(cell_index) row_pv = get_poss_row_vals(cell_index) col_pv = get_poss_col_vals(cell_index) pv = sqr_pv & row_pv & col_pv return pv end def get_possible_values_for_other_cells(cell_index) oc_sqr_pv = get_pv_for_sqr(cell_index) oc_row_pv = get_pv_for_row(cell_index) oc_col_pv = get_pv_for_col(cell_index) oc_pv = oc_sqr_pv & oc_row_pv & oc_col_pv end def solve_cell(cell_index) pv = get_possible_values_for_cell(cell_index) if(pv.length == 1) @board[cell_index] = pv[0] elsif pv.length > 1 oc_pv = get_possible_values_for_other_cells(cell_index) pv = pv - oc_pv if(pv.length == 1) @board[cell_index] = pv[0] end end end def get_square_for_cell(cell_index) square = nil @squares.each {|sq| square = sq unless !sq.member?(cell_index)} return square end def get_row_for_cell(cell_index) if(cell_index < 9) cell_index = 0 else cell_index = (cell_index / 9 * 9) end row_cells = Array.new(9) {|i| cell_index+i} return row_cells end def get_col_for_cell(cell_index) cell_index = cell_index - (cell_index/9*9) unless cell_index < 9 col_cells = Array.new(9){|i| cell_index + (9*i)} return col_cells end def get_possible_values(cell_index, cells) pos_vals = Array.new cells.each do |i| cell = @board[i] if cell == 0 && i != cell_index pv = get_possible_values_for_cell(i) pos_vals = pos_vals | pv end end return pos_vals.sort end end