Skip to content

Instantly share code, notes, and snippets.

@tuwukee
Last active August 29, 2015 14:09
Show Gist options
  • Save tuwukee/de2dc102ec097234a15b to your computer and use it in GitHub Desktop.
Save tuwukee/de2dc102ec097234a15b to your computer and use it in GitHub Desktop.
class SudokuBoard
def initialize(filename)
init_defaults()
@boards = parse_file(filename)
@solved = []
@boards.each do |board|
solved_board = solve(parse_board(board))
@solved.push solved_board
display(solved_board)
end
end
def print_result_to(filename)
begin
file = File.open(filename, 'w')
@solved.each do |board|
file.write("#{board.values.join('')}\n")
end
rescue IOError => e
puts "ERROR: can't write to file"
ensure
file.close unless file == nil
end
end
private
def parse_file(filename)
file = File.read(filename)
file.split(/[=]+\r?\n/).inject([]) do |boards,board|
boards.push board.gsub!(/\n/, '')
end
end
def merge(str1, str2)
line = []
str1.each_char {|x| str2.each_char {|y| line.push (x + y) } }
line
end
def init_defaults
@digits = '123456789'
@cols = @digits
@rows = @digits
@cells = merge(@rows, @cols)
@vertical = []
@horizontal = []
@cubes = []
@units = {}
@scope = {}
@cols.each_char {|c| @vertical.push merge(@rows, c)}
@rows.each_char {|r| @horizontal.push merge(r, @cols)}
cube_triples = @digits.scan(/.../)
cube_triples.each do |vl|
cube_triples.each do |hl|
@cubes.push merge(vl,hl)
end
end
opts = @vertical + @horizontal + @cubes
@cells.each do |c|
opts.each do |u|
if u.include?(c)
@units[c] ||= []
@units[c].push u
end
end
@scope[c] = (@units[c].flatten - [c]).uniq
end
end
def board_values(board)
chars = []
board_hash = {}
board.each_char do |c|
chars.push c if(@digits.include?(c) || '0._'.include?(c))
end
@cells.zip(chars).each {|c| board_hash[c[0]] = c[1]}
board_hash
end
def nominate(board, cl, c)
vals = board[cl].gsub(c, '')
calls = []
vals.each_char do |c2|
calls.push exclude(board, cl, c2)
end
calls.all? ? board : false
end
def display(board)
lines = board.values.each_slice(9)
lines.each do |line|
puts line.join('')
end
puts '='*9
end
def exclude(board, cl, c)
return board unless board[cl].include?(c)
board[cl] = board[cl].gsub(c,'')
size = board[cl].size
if size == 0
return false
elsif size == 1
c2 = board[cl]
return false unless @scope[cl].inject([]){|temp, cl2| temp.push exclude(board, cl2, c2)}.all?
end
@units[cl].each do |u|
vals = u.select {|x| x if board[x].include?(c) }
size = vals.size
return false if(size == 0 || (size == 1 && !nominate(board, vals[0], c)))
end
board
end
def parse_board(initial_board)
board = {}
@cells.each do |c|
board[c] = @digits
end
board_values(initial_board).each do |key, val|
return false if(@digits.include?(val) && !nominate(board, key, val))
end
board
end
def solve(board)
return false unless board
sizes = []
temp = {}
@cells.each do |c|
size = board[c].size
sizes.push size == 1
temp[c] = size if size > 1
end
return board if sizes.all?
min_val = temp.min_by{|k,v| v}
results = []
board[min_val[0]].each_char do |c|
x = solve(nominate(board.clone, min_val[0], c))
return x if x
end
false
end
end
board = SudokuBoard.new('test2.txt')
board.print_result_to('result.txt')
@lappi-lynx
Copy link

crazy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment