Skip to content

Instantly share code, notes, and snippets.

@barreyro
Last active August 29, 2015 14:22
Show Gist options
  • Save barreyro/a3f69322b6d74e7bf93f to your computer and use it in GitHub Desktop.
Save barreyro/a3f69322b6d74e7bf93f to your computer and use it in GitHub Desktop.
After given a string that represents a sudoku puzzle, this Ruby class will solve the missing pieces. 0's are represented as empty cells. To try other examples, uncomment line 188/189.
class Sudoku
def initialize(board_string)
@board_string = board_string
@board = board_string.split("").map(&:to_i)
@blocks = [ @block_012 = [0, 1, 2], @block_345 = [3, 4, 5], @block_678 = [6, 7, 8] ]
end
# INPUT: index
# OUTPUT: two-coordinate array
def index_to_coord(index)
index.divmod(9)
end
# INPUT: two-coordinate array
# OUTPUT: index
def coord_to_index(array)
array[0] * 9 + array[1]
end
# INPUT: num in question and the corresponding array it will go in
# OUTPUT: boolean
def check_column(num, coord_array)
(0..8).each do |row|
index = coord_to_index([row, coord_array[1]])
return false if @board[index] == num
end
true
end
# INPUT: num in question and the corresponding array it will go in
# OUTPUT: boolean
def check_row(num, coord_array)
(0..8).each do |col|
return false if @board[coord_to_index([coord_array[0], col])] == num
end
true
end
#INPUT: num in question and the corresponding array it will go in
#OUTPUT: boolean
def check_block(num, coord_array)
if @block_012.include?(coord_array[0])
rows = @block_012
elsif @block_345.include?(coord_array[0])
rows = @block_345
elsif @block_678.include?(coord_array[0])
rows = @block_678
end
if @block_012.include?(coord_array[1])
cols = @block_012
elsif @block_345.include?(coord_array[1])
cols = @block_345
elsif @block_678.include?(coord_array[1])
cols = @block_678
end
rows.each do |row|
cols.each do |col|
return false if @board[coord_to_index([row, col])] == num
end
end
true
end
#IF check_column && check_row && check_square are true
#OUTPUT: is either a number or 0
def check_if_we_can_fill_a_cell(coord_array)
possible_num = []
(1..9).each do | num_to_check |
# check if num_to_check is possible to put in a cell
if check_column(num_to_check,coord_array) &&
check_row(num_to_check, coord_array) &&
check_block(num_to_check, coord_array)
# push num_to_check into possible_num
possible_num << num_to_check
end
end
# check if we only have one possibility and if TRUE fill the cell with the number
if possible_num.length == 1
fill_it_in(possible_num[0], coord_array)
# otherwise return false
end
end
# INPUT: number to put in & coord_array
# This method will check whether the check_colum, check_row and check_square
def fill_it_in(num, coord_array)
@board[coord_to_index(coord_array)] = num
sleep(0.1)
reset_screen!
to_s
end
def check_to_see_if_there_are_any_more_blanks
@board.include?(0)
end
def all_correct?
# Check Each Row
(0..8).each do |row|
row_sum = 0
(0..8).each do |col|
row_sum += @board[coord_to_index([row, col])]
end
if row_sum != 45
return false
end
end
# Check Each Col
(0..8).each do |col|
col_sum = 0
(0..8).each do |row|
col_sum += @board[coord_to_index([row, col])]
end
if col_sum != 45
return false
end
end
# Checks each block
# @blocks = [ @block_012 = [0, 1, 2], @block_345 = [3, 4, 5], @block_678 = [6, 7, 8] ]
@blocks.each do | block_in_a_row |
@blocks.each do | block_in_a_col |
block_sum = 0
block_in_a_row.each do |row|
block_in_a_col.each do |col|
block_sum += @board[coord_to_index([row, col])]
end
end
return false if block_sum != 45
end
end
end
def solve!
while @board.include?(0)
#iterate through @board (which is an array)
@board.each_with_index do | cell, idx |
if cell == 0
cell_coord = index_to_coord(idx)
check_if_we_can_fill_a_cell(cell_coord)
end
end
end
puts all_correct? ? " ~*~ Success! ~*~ " : " ~*~ Sorry, try again. ~*~ "
puts "-"*31
puts " /\\-/\\ /\\-/\\ /\\-/\\ "
puts " (=^Y^=) (=^Y^=) (=^Y^=) "
puts " (>o<) (>o<) (>o<) "
end
# Returns a string representing the current state of the board
def to_s
puts "-"*31
puts " "*10 + "SUDOKU BOARD" + " "*10
(0..8).each do |times|
if times%3 == 0
puts "-"*31
end
row = @board[9*times..9*times+2] + ["|"] + @board[9*times+3..9*times+5] + ["|"] + @board[9*times+6..9*times+8]
puts row.join(' ')
end
puts "-"*31
end
def clear_screen!
print "\e[2J"
end
# Moves "cursor" back to the upper left.
def move_to_home!
print "\e[H"
end
def reset_screen!
clear_screen!
move_to_home!
end
end
#board_string = "608730000200000460000064820080005701900618004031000080860200039050000100100456200"
#board_string = "080020000040500320020309046600090004000640501134050700360004002407230600000700450"
board_string = "105802000090076405200400819019007306762083090000061050007600030430020501600308900"
game = Sudoku.new(board_string)
game.to_s
game.solve!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment