Last active
August 29, 2015 14:22
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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