Skip to content

Instantly share code, notes, and snippets.

@chadwickdonald
Created June 25, 2012 22:20
Show Gist options
  • Save chadwickdonald/2991740 to your computer and use it in GitHub Desktop.
Save chadwickdonald/2991740 to your computer and use it in GitHub Desktop.
sodoku
class SudokuBoard
def initialize(board_str)
@example_board ="123456789578139624496872153952381467641297835387564291719623548864915372235748916"
@board = board_str.split("").map { |value| Cell.new(value.to_i) }
@groups = []
(generate_rows + generate_cols + generate_grids).each do |group_member_indices|
group_cell_members = group_member_indices.map { |index| @board[index] }
@groups << Group.new(group_cell_members)
end
end
def pretty_print
cell_values_to_print = cell_values
while !cell_values_to_print.empty?
line = cell_values_to_print.slice!(0..8)
puts line
end
puts "---------"
end
def solve
puts cell_values
while cell_values.include?('0')
@board.each do |cell|
cell.refresh_state
end
puts cell_values
#pretty_print
end
cell_values
end
def cell_values
values = []
@board.each { |cell| values << cell.value }
values.join
end
def generate_rows
ar = (0..80).to_a
rows = []
while !ar.empty?
rows << ar.shift(9)
end
rows
end
def generate_cols
ar = (0..80).to_a
cols = Array.new(9,[])
ar.each { |index| cols[index % 9] += [index] }
cols
end
def generate_grids
ar = (0..80).to_a
grids = Array.new(9,[])
ar.each { |index| grids[(index / 9 / 3 * 3) + ((index % 9) / 3)] += [index]}
grids
end
end
class Group
def initialize(members_ar) #pass in array of initial board settings
@cells = members_ar
@cells.each { |cell| cell.add_group(self)}
end
def other_cells_in_group(cell)
@cells - [cell]
end
end
class Cell
attr_reader :value, :blacklist
def initialize(value)
@value = value
@groups = []
solved? ? set_value(value) : @blacklist = []
end
def set_value(value)
@value = value
@blacklist = (1..9).to_a - [@value]
end
def add_group(group)
@groups << group
end
def refresh_state
@groups.each do|group|
other_cells = group.other_cells_in_group(self)
update_blacklist(other_cells.map { |cell| cell.value })
determine_logical_value(other_cells.map { |cell| cell.value })
determine_inferential_value(other_cells.map { |cell| cell.blacklist })
end
end
def update_blacklist(values_ar)
values_ar.each do |value|
@blacklist << value unless (@blacklist.include?(value) || value == 0)
end
end
def determine_logical_value(values_ar)
if !values_ar.include?(0)
set_value(((1..9).to_a - values_ar)[0])
end
end
def determine_inferential_value(blacklist_ar)
surviving_possibilities = (1..9).to_a
blacklist_ar.each do |blacklist|
surviving_possibilities &= blacklist
end
if surviving_possibilities.length == 1
set_value(surviving_possibilities[0])
end
end
def solved?
@value > 0
end
end
class Utils
def self.get_files(directory)
files = []
Dir.foreach(directory) do |file_name|
if !file_name.scan(".unsolved.txt").empty?
files << file_name
end
end
files
end
def self.get_lines_from_file(filename)
lines = []
file =File.open(filename, "r")
while (line = file.gets)
lines << line
end
lines
end
def self.write_to_file(filename, text)
filename.gsub!("unsolved", "solved")
File.open(filename, "a").write(text)
end
end
class Player
def play_lots_of_sudoku(directory)
files = Utils.get_files(directory)
files.each do |file|
lines = Utils.get_lines_from_file(file)
lines.each do |l|
game = SudokuBoard.new(l.chomp)
Utils.write_to_file(file, game.solve + "\n")
end
end
end
end
#board = SudokuBoard.new("619030040270061008000047621486302079000014580031009060005720806320106057160400030")
#board = SudokuBoard.new("096040001100060004504810390007950043030080000405023018010630059059070830003590007")
#board = SudokuBoard.new("396040001100369004504810396007951043931480005405023918710630459659174832043590167")
#board.solve
# util = Utils.new
# p util.get_files(".")
# p util.get_lines_from_file("sodoku1.unsolved.txt")
player = Player.new
player.play_lots_of_sudoku(".")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment