Skip to content

Instantly share code, notes, and snippets.

@andmcgregor
Created June 10, 2013 05:24
Show Gist options
  • Save andmcgregor/5746717 to your computer and use it in GitHub Desktop.
Save andmcgregor/5746717 to your computer and use it in GitHub Desktop.
Brute force sudoku (work in progress). Need to: - make the code ALOT more efficient. I have a few ideas how to do this. - improve found algorithm to actually check that the board is solved (rather than just adding up the numbers and seeing if they equal 405). - pause the search once a solution is found.
class SudokuCell
attr_accessor :index, :value, :row, :column, :box
def initialize(initial_value, index)
@value = initial_value != 0 ? initial_value : 0
@index = index.to_i
@row = (0..81).to_a[((index/9)*9..(index/9)*9+8)]
@column, at_index, incrementor = [], index, +9
until @column.count == 9 do
if at_index < 0
incrementor = +9
elsif at_index > 80
incrementor = -9
else
@column << at_index if [email protected]?(at_index)
end
at_index += incrementor
end
@box = get_box
end
def get_box
box_indexes = [[0,1,2,9,10,11,18,19,20],[3,4,5,12,13,14,21,22,23],[6,7,8,15,16,17,24,25,26],[27,28,29,36,37,38,45,46,47],[30,31,32,39,40,41,48,49,50],[33,34,35,42,43,44,51,52,53],[54,55,56,63,64,65,72,73,74],[57,58,59,66,67,68,75,76,77],[60,61,62,69,70,71,78,79,80]]
box_indexes.each do |box|
return box if box.include?(@index)
end
end
end
class Sudoku
attr_accessor :counter
def initialize(board_string)
@counter = 1
i = -1
@board = board_string.chomp.split("").map {|value| i += 1; SudokuCell.new(value.to_i, i) }
end
def solved?
sum = 0
@board.each {|cell| sum += cell.value if cell.value.is_a? Integer }
sum == 405
end
def solve!
count = @board.select {|cell| cell.value == 0 }.size
#print_sudoku_and_trace([0,0,0,0,0,0,0,0,0,0,0])
recursive(count)
end
def recursive(trace = [], length)
if length != 0
length -= 1
(1..9).each do |x|
temp_trace = trace.clone << x
recursive(temp_trace, length)
temp_trace = []
end
else
puts "\e[H\e[2J" if @counter % 50000 == 0
puts print_sudoku_and_trace(trace) if @counter % 50000 == 0
puts "Recursions: #{@counter}" if @counter % 50000 == 0
@counter += 1
end
end
def print_sudoku_and_trace(trace)
counter = 0
trace_counter = 0
str = ""
board = @board.clone
board.each do |cell|
if cell.value != 0
str += cell.value.to_s + " "
counter += 1
else
str += trace[trace_counter].to_s + " "
trace_counter += 1
counter += 1
end
if counter % 9 == 0
str += "\n"
end
end
puts str
end
def to_s
board = @board.clone
str = ""
9.times do
board.shift(9).each do |cell|
str += cell.value.to_s + " "
end
str += "\n"
end
str
end
end
game = Sudoku.new('096040001100060004504810390007950043030080000405023018010630059059070830003590007')
game.solve!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment