Created
May 11, 2010 09:39
-
-
Save thomasfedb/397122 to your computer and use it in GitHub Desktop.
This file contains 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
# sudoku.rb | |
# A program to solve sodoku. | |
require './includes/utill.rb' | |
require './includes/cell.rb' | |
require './includes/group.rb' | |
require './includes/puzzle.rb' | |
class Sudoku | |
def initialize | |
@puzzle = Puzzle.new | |
end | |
def sample | |
".2.178.3..4.3.2.9.1.......6..86.35..3.......4..67.92...8.9.1.6..1.436.5." | |
end | |
def show | |
print @puzzle.to_s | |
end | |
# Read in sudoku data | |
def read(data) | |
data.gsub!(".", "0") | |
data.delete! '^0-9_' | |
grid_data = data.split("") | |
(0..80).to_a.each do |cell| | |
if grid_data[cell].to_i != 0 | |
@puzzle.set_cell(cell, grid_data[cell].to_i) | |
end | |
end | |
end | |
# Now we have the data, the solving begings! | |
def solve | |
end | |
#private | |
def reduce | |
end | |
def hidden_singles | |
end | |
[:solved?, :to_s, :to_grid].each do |method| | |
define_method method do | |
@puzzle.call(method) | |
end | |
end | |
private | |
[:cells, :each_cell, :groups, :each_group].each do |method| | |
define_method method do | |
@puzzle.call(method) | |
end | |
end | |
end | |
# utill.rb | |
class Array | |
define_method "/" do |len| | |
a = [] | |
each_with_index do |x,i| | |
a << [] if i % len == 0 | |
a.last << x | |
end | |
a | |
end | |
def count(item) | |
count = 0 | |
each do |x| | |
if x == item | |
count += 1 | |
end | |
end | |
count | |
end | |
end | |
# puzzle.rb | |
class Puzzle | |
attr_reader :cells, :groups | |
def initialize | |
@grid_numbers = (0..80).to_a | |
@cells = [] | |
@grid_numbers.each do |cell| | |
@cells[cell] = Cell.new(cell) | |
end | |
@groups = [] | |
row_contents = @grid_numbers / 9 | |
column_contents = [] | |
(0..8).to_a.each do |x| | |
column_contents[x] = [] | |
row_contents.each do |row| | |
column_contents[x] << row[x] | |
end | |
end | |
box_contents = [] | |
3.times do |x| | |
row_a = row_contents[x * 3] / 3 | |
row_b = row_contents[x * 3 + 1] / 3 | |
row_c = row_contents[x * 3 + 2] / 3 | |
3.times do |y| | |
box_contents << row_a[y] + row_b[y] + row_c[y] | |
end | |
end | |
group_contents = box_contents + row_contents + column_contents | |
group_contents.each do |group| | |
children = [] | |
group.each do |child_index| | |
children << @cells[child_index] | |
end | |
@groups << Group.new(children) | |
end | |
puts @groups.inspect | |
@groups.each do |group| | |
group.setup | |
end | |
end | |
def each_cell | |
@cells.each do |cell| | |
yeild(cell) | |
end | |
end | |
def each_group | |
@groups.each do |group| | |
yeild(group) | |
end | |
end | |
def get_cell(x, y) | |
@cells[x + 9 * y] | |
end | |
def set_cell(pos, value) | |
@cells[pos].must_be(value) | |
end | |
def solved? | |
@grid_numbers.each do |cell| | |
if not @cells[cell].solved? | |
return false | |
end | |
end | |
true | |
end | |
def to_grid | |
grid = [] | |
(0..8).to_a.each do |y| | |
grid[y] = [] | |
(0..8).to_a.each do |x| | |
if get_cell(x, y).solved? | |
grid[y][x] = get_cell(x, y).value | |
else | |
grid[y][x] = nil | |
end | |
end | |
end | |
grid | |
end | |
def to_s | |
out = "" | |
grid.each do |row| | |
row.each do |cell| | |
if cell == nil | |
out << ". " | |
else | |
out << cell.to_s << " " | |
end | |
end | |
out << "\n" | |
end | |
out | |
end | |
end | |
# cell.rb | |
class Position | |
attr_reader :id | |
def initialize(id) | |
@id = id | |
end | |
def x | |
@id % 9 | |
end | |
def y | |
(@id / 9).floor | |
end | |
end | |
class Cell | |
attr_reader :parents, :position | |
def initialize(id) | |
@possible = (1..9).to_a | |
@parents = [] | |
@id = Position.new(id) | |
end | |
def cant_be(value) | |
@possible.delete value | |
end | |
def must_be(value) | |
@possible = [value] | |
each_sibling do |sibling| | |
sibling.cant_be(value) | |
end | |
each_parent do |parent| | |
parent.used(value) | |
end | |
end | |
def solved? | |
@possible.size == 1 | |
end | |
def can_be | |
@possible | |
end | |
def value | |
@possible.first if solved? | |
end | |
def each_parent | |
@parents.each do |parent| | |
yeild(parents) | |
end | |
end | |
def belongs_to(parent) | |
@parents << parent | |
end | |
def siblings | |
siblings = [] | |
@parents.each do |parent| | |
siblings.concat(parent.children) | |
end | |
slibings.uniq!.delete self | |
end | |
def each_sibling | |
siblings.each do |sibling| | |
yeild(sibling) | |
end | |
end | |
end | |
# group.rb | |
class Group | |
attr_reader :children | |
def initialize(children) | |
@children = children | |
@unused = (1..9).to_a | |
end | |
def setup | |
@children.each do |child| | |
child.belongs_to(self) | |
end | |
end | |
def each_child | |
@children.each do |child| | |
yeild(child) | |
end | |
end | |
def used(value) | |
@unused.delete value | |
if @unused.size == 1 | |
each_child do |child| | |
if not child.solved? | |
child.must_be(@unused.first) | |
end | |
end | |
end | |
end | |
def solved? | |
@unused.empty? | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment