Skip to content

Instantly share code, notes, and snippets.

@benwyrosdick
Created April 1, 2009 06:02
Show Gist options
  • Save benwyrosdick/88562 to your computer and use it in GitHub Desktop.
Save benwyrosdick/88562 to your computer and use it in GitHub Desktop.
class Sudoku
attr_accessor :board
Possibilities = (1..9).to_a
def initialize(board_in = nil)
self.board = []
9.times do # rows
row = []
9.times do # cells
row << Sudoku::Possibilities.clone
end
self.board << row
end
if board_in
rows = []
board_in.each_line do |line|
sanitized_line = line.gsub(/\s/, '')
rows << sanitized_line if sanitized_line.length == 9
end
raise "Invalid Board input" unless rows.length == 9
9.times do |row_index|
9.times do |column_index|
start_val = rows[row_index][column_index,1].to_i
if start_val > 0
self.board[row_index][column_index] = [start_val]
end
end
end
end
end
def solved?
self.board.each do |row|
return false if row.any?{|c| c.length > 1}
end
return true
end
def valid?
[:row, :col, :box].each do |selector|
9.times do |selector_index|
selection = self.send("#{selector}_#{selector_index + 1}")
return false unless selection.flatten.sort == Possibilities
end
end
return true
end
def solve
solution_possible = true
while solution_possible
next if self.elimination
next if self.singletons
next if self.pairs
next if self.deduction
next if self.brute_force
return self.solved?
end
end
def elimination
start_board_size = self.board.flatten.length
[:row, :col, :box].each do |selector|
9.times do |selector_index|
selection = self.send("#{selector}_#{selector_index + 1}")
known_values = selection.find_all{|c| c.length == 1}.flatten
9.times do |cell_index|
cell = selection[cell_index]
cell.delete_if{|val| known_values.include?(val)} if cell.length > 1
end
end
end
start_board_size != self.board.flatten.length
end
def singletons
start_board_size = self.board.flatten.length
[:row, :col, :box].each do |selector|
9.times do |selector_index|
selection = self.send("#{selector}_#{selector_index + 1}")
9.times do |value_index|
value = value_index + 1
value_count = 0
selection.each{|cell| value_count += 1 if cell.include?(value)}
if value_count == 1
selection.each{|cell| cell.delete_if{|val| val != value} if cell.include?(value)}
end
end
end
end
start_board_size != self.board.flatten.length
end
# TODO: Implement
def pairs
start_board_size = self.board.flatten.length
start_board_size != self.board.flatten.length
end
# TODO: Implement
def deduction
start_board_size = self.board.flatten.length
start_board_size != self.board.flatten.length
end
# TODO: Implement
def brute_force
start_board_size = self.board.flatten.length
start_board_size != self.board.flatten.length
end
def to_s
res = "+---+---+---+\n"
res << "|"+row_1[0,3].map{|c| cell_print(c)}.join+"|"+row_1[3,3].map{|c| cell_print(c)}.join+"|"+row_1[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "|"+row_2[0,3].map{|c| cell_print(c)}.join+"|"+row_2[3,3].map{|c| cell_print(c)}.join+"|"+row_2[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "|"+row_3[0,3].map{|c| cell_print(c)}.join+"|"+row_3[3,3].map{|c| cell_print(c)}.join+"|"+row_3[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "+---+---+---+\n"
res << "|"+row_4[0,3].map{|c| cell_print(c)}.join+"|"+row_4[3,3].map{|c| cell_print(c)}.join+"|"+row_4[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "|"+row_5[0,3].map{|c| cell_print(c)}.join+"|"+row_5[3,3].map{|c| cell_print(c)}.join+"|"+row_5[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "|"+row_6[0,3].map{|c| cell_print(c)}.join+"|"+row_6[3,3].map{|c| cell_print(c)}.join+"|"+row_6[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "+---+---+---+\n"
res << "|"+row_7[0,3].map{|c| cell_print(c)}.join+"|"+row_7[3,3].map{|c| cell_print(c)}.join+"|"+row_7[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "|"+row_8[0,3].map{|c| cell_print(c)}.join+"|"+row_8[3,3].map{|c| cell_print(c)}.join+"|"+row_8[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "|"+row_9[0,3].map{|c| cell_print(c)}.join+"|"+row_9[3,3].map{|c| cell_print(c)}.join+"|"+row_9[6,3].map{|c| cell_print(c)}.join+"|\n"
res << "+---+---+---+\n"
res.gsub(/0/, '_')
end
def cell_print(cell)
if cell.length == 1
cell.first.to_s
else
"_"
end
end
def method_missing(meth, *args)
if meth.to_s =~ /row_(\d)/
@board[$1.to_i - 1]
elsif meth.to_s =~ /col_(\d)/
col = []
@board.each do |row|
col << row[$1.to_i - 1]
end
col
elsif meth.to_s =~ /box_(\d)/
box = []
actual_box = $1.to_i - 1
row = actual_box / 3
col = actual_box % 3
0.upto 2 do |i|
0.upto 2 do |j|
box << @board[row*3+i][col*3+j]
end
end
box
else
super.send(meth, args)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment