Created
March 21, 2018 16:32
-
-
Save joegiralt/66d24e0e11f466cef333e459fad1ed86 to your computer and use it in GitHub Desktop.
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
require 'set' | |
class Board | |
attr_accessor :rows, :columns, :grids, :puzzle, :completed_set | |
COL_LOOKUP = {a: 0, b: 1, c: 2, d:3, e: 4, f:5, g:6, h:7, i:8 } | |
GRID_LOOKUP = { | |
[:a,1] => 1, | |
[:a,2] => 1, | |
[:a,3] => 1, | |
[:b,1] => 1, | |
[:b,2] => 1, | |
[:b,3] => 1, | |
[:c,1] => 1, | |
[:c,2] => 1, | |
[:c,3] => 1, | |
[:d,1] => 2, | |
[:d,2] => 2, | |
[:d,3] => 2, | |
[:e,1] => 2, | |
[:e,2] => 2, | |
[:e,3] => 2, | |
[:f,1] => 2, | |
[:f,2] => 2, | |
[:f,3] => 2, | |
[:g,1] => 3, | |
[:g,2] => 3, | |
[:g,3] => 3, | |
[:h,1] => 3, | |
[:h,2] => 3, | |
[:h,3] => 3, | |
[:i,1] => 3, | |
[:i,2] => 3, | |
[:i,3] => 3, | |
[:a,4] => 4, | |
[:a,5] => 4, | |
[:a,6] => 4, | |
[:b,4] => 4, | |
[:b,5] => 4, | |
[:b,6] => 4, | |
[:c,4] => 4, | |
[:c,5] => 4, | |
[:c,6] => 4, | |
[:d,4] => 5, | |
[:d,5] => 5, | |
[:d,6] => 5, | |
[:e,4] => 5, | |
[:e,5] => 5, | |
[:e,6] => 5, | |
[:f,4] => 5, | |
[:f,5] => 5, | |
[:f,6] => 5, | |
[:g,4] => 6, | |
[:g,5] => 6, | |
[:g,6] => 6, | |
[:h,4] => 6, | |
[:h,5] => 6, | |
[:h,6] => 6, | |
[:i,4] => 6, | |
[:i,5] => 6, | |
[:i,6] => 6, | |
[:a,7] => 7, | |
[:a,8] => 7, | |
[:a,9] => 7, | |
[:b,7] => 7, | |
[:b,8] => 7, | |
[:b,9] => 7, | |
[:c,7] => 7, | |
[:c,8] => 7, | |
[:c,9] => 7, | |
[:d,7] => 8, | |
[:d,8] => 8, | |
[:d,9] => 8, | |
[:e,7] => 8, | |
[:e,8] => 8, | |
[:e,9] => 8, | |
[:f,7] => 8, | |
[:f,8] => 8, | |
[:f,9] => 8, | |
[:g,7] => 9, | |
[:g,8] => 9, | |
[:g,9] => 9, | |
[:h,7] => 9, | |
[:h,8] => 9, | |
[:h,9] => 9, | |
[:i,7] => 9, | |
[:i,8] => 9, | |
[:i,9] => 9, | |
} | |
def initialize(init_state = nil) | |
@puzzle = init_state.nil? ? gen_empty_puzzle : init_state | |
@rows = init_rows | |
@columns = init_cols | |
@grids = init_grids | |
@completed_set = (1..9).to_set | |
end | |
def insert_cell(col, row, value) | |
return if invalid?(col, row, value) | |
rows[row].add(value) | |
columns[col].add(value) | |
puzzle[COL_LOOKUP[col]][row - 1] = value if puzzle[COL_LOOKUP[col]][row - 1] == 0 | |
end | |
def read_cell(col, row) | |
cell = puzzle[COL_LOOKUP[col]][row - 1] | |
if cell.nil? || cell.zero? | |
'X' | |
else | |
cell | |
end | |
end | |
def values_in_row(row) | |
rows[row] | |
end | |
def values_in_column(col) | |
columns[col] | |
end | |
def values_in_grid(col, row) | |
grids[GRID_LOOKUP[[col, row]]] | |
end | |
def valid_values_for_cell(col, row) | |
(completed_set - (values_in_row(row) + values_in_column(col) + values_in_grid(col, row))).to_a | |
end | |
def display_puzzle | |
puts """ | |
COLUMNS A-I | |
A B C D E F G H I | |
ROW 1 | #{ read_cell(:a, 1)} | #{read_cell(:b, 1)} | #{ read_cell(:c, 1)} | #{read_cell(:d, 1)} | #{ read_cell(:e, 1)} | #{read_cell(:f, 1)} | #{ read_cell(:g, 1)} | #{read_cell(:h, 1)} | #{ read_cell(:i, 1)} | |
----------------------------------- | |
ROW 2 | #{ read_cell(:a, 2)} | #{read_cell(:b, 2)} | #{ read_cell(:c, 2)} | #{read_cell(:d, 2)} | #{ read_cell(:e, 2)} | #{read_cell(:f, 2)} | #{ read_cell(:g, 2)} | #{read_cell(:h, 2)} | #{ read_cell(:i, 2)} | |
----------------------------------- | |
ROW 3 | #{ read_cell(:a, 3)} | #{read_cell(:b, 3)} | #{ read_cell(:c, 3)} | #{read_cell(:d, 3)} | #{ read_cell(:e, 3)} | #{read_cell(:f, 3)} | #{ read_cell(:g, 3)} | #{read_cell(:h, 3)} | #{ read_cell(:i, 3)} | |
----------------------------------- | |
ROW 4 | #{ read_cell(:a, 4)} | #{read_cell(:b, 4)} | #{ read_cell(:c, 4)} | #{read_cell(:d, 4)} | #{ read_cell(:e, 4)} | #{read_cell(:f, 4)} | #{ read_cell(:g, 4)} | #{read_cell(:h, 4)} | #{ read_cell(:i, 4)} | |
----------------------------------- | |
ROW 5 | #{ read_cell(:a, 5)} | #{read_cell(:b, 5)} | #{ read_cell(:c, 5)} | #{read_cell(:d, 5)} | #{ read_cell(:e, 5)} | #{read_cell(:f, 5)} | #{ read_cell(:g, 5)} | #{read_cell(:h, 5)} | #{ read_cell(:i, 5)} | |
----------------------------------- | |
ROW 6 | #{ read_cell(:a, 6)} | #{read_cell(:b, 6)} | #{ read_cell(:c, 6)} | #{read_cell(:d, 6)} | #{ read_cell(:e, 6)} | #{read_cell(:f, 6)} | #{ read_cell(:g, 6)} | #{read_cell(:h, 6)} | #{ read_cell(:i, 6)} | |
----------------------------------- | |
ROW 7 | #{ read_cell(:a, 7)} | #{read_cell(:b, 7)} | #{ read_cell(:c, 7)} | #{read_cell(:d, 7)} | #{ read_cell(:e, 7)} | #{read_cell(:f, 7)} | #{ read_cell(:g, 7)} | #{read_cell(:h, 7)} | #{ read_cell(:i, 7)} | |
----------------------------------- | |
ROW 8 | #{ read_cell(:a, 8)} | #{read_cell(:b, 8)} | #{ read_cell(:c, 8)} | #{read_cell(:d, 8)} | #{ read_cell(:e, 8)} | #{read_cell(:f, 8)} | #{ read_cell(:g, 8)} | #{read_cell(:h, 8)} | #{ read_cell(:i, 8)} | |
----------------------------------- | |
ROW 9 | #{ read_cell(:a, 9)} | #{read_cell(:b, 9)} | #{ read_cell(:c, 9)} | #{read_cell(:d, 9)} | #{ read_cell(:e, 9)} | #{read_cell(:f, 9)} | #{ read_cell(:g, 9)} | #{read_cell(:h, 9)} | #{ read_cell(:i, 9)} | |
""" | |
end | |
private | |
def init_rows | |
{ | |
1 => Set.new(puzzle.map{ |column| column[0] }), | |
2 => Set.new(puzzle.map{ |column| column[1] }), | |
3 => Set.new(puzzle.map{ |column| column[2] }), | |
4 => Set.new(puzzle.map{ |column| column[3] }), | |
5 => Set.new(puzzle.map{ |column| column[4] }), | |
6 => Set.new(puzzle.map{ |column| column[5] }), | |
7 => Set.new(puzzle.map{ |column| column[6] }), | |
8 => Set.new(puzzle.map{ |column| column[7] }), | |
9 => Set.new(puzzle.map{ |column| column[8] }), | |
} | |
end | |
def init_cols | |
{ | |
a: Set.new(puzzle[0]), | |
b: Set.new(puzzle[1]), | |
c: Set.new(puzzle[2]), | |
d: Set.new(puzzle[3]), | |
e: Set.new(puzzle[4]), | |
f: Set.new(puzzle[5]), | |
g: Set.new(puzzle[6]), | |
h: Set.new(puzzle[7]), | |
i: Set.new(puzzle[8]), | |
} | |
end | |
def init_grids | |
{ | |
1 => Set.new([puzzle[0][0..2],[puzzle[1][0..2]],[puzzle[2][0..2]]].flatten), | |
2 => Set.new([puzzle[3][0..2],[puzzle[4][0..2]],[puzzle[5][0..2]]].flatten), | |
3 => Set.new([puzzle[6][0..2],[puzzle[7][0..2]],[puzzle[8][0..2]]].flatten), | |
4 => Set.new([puzzle[0][3..5],[puzzle[1][3..5]],[puzzle[2][3..5]]].flatten), | |
5 => Set.new([puzzle[3][3..5],[puzzle[4][3..5]],[puzzle[5][3..5]]].flatten), | |
6 => Set.new([puzzle[6][3..5],[puzzle[7][3..5]],[puzzle[8][3..5]]].flatten), | |
7 => Set.new([puzzle[0][6..8],[puzzle[1][6..8]],[puzzle[2][6..8]]].flatten), | |
8 => Set.new([puzzle[3][6..8],[puzzle[4][6..8]],[puzzle[5][6..8]]].flatten), | |
9 => Set.new([puzzle[6][6..8],[puzzle[7][6..8]],[puzzle[8][6..8]]].flatten), | |
} | |
end | |
def gen_empty_puzzle | |
(1..9).to_a.map{|int| (1..9).to_a.map{|int2| nil}} | |
end | |
def invalid?(col, row, value) | |
[ | |
rows[row].member?(value), | |
columns[col].member?(value), | |
grids[GRID_LOOKUP[[col, row]]].member?(value) | |
].include?(true) | |
end | |
end | |
class Solver | |
attr_accessor :board | |
ROW_CHOICES = (1..9).to_a | |
COL_CHOICES = (:a..:i).to_a | |
def initialize(board) | |
@board = board | |
end | |
def availible_numbers(col, row) | |
board.valid_values_for_cell(col, row) | |
end | |
def solve! | |
81.times do | |
ROW_CHOICES.each do |row| | |
COL_CHOICES.each do |col| | |
board.insert_cell(col, row, availible_numbers(col, row).sample) | |
end | |
end | |
end | |
end | |
end | |
SEED1 = [ | |
[6, 8, 5, 0, 0, 0, 0, 0, 0], | |
[3, 1, 9, 0, 0, 0, 0, 0, 0], | |
[7, 2, 4, 0, 0, 0, 0, 0, 0], | |
[0, 0, 0, 2, 1, 8, 0, 0, 0], | |
[0, 0, 0, 4, 5, 6, 0, 0, 0], | |
[0, 0, 0, 9, 7, 3, 0, 0, 0], | |
[0, 0, 0, 0, 0, 0, 2, 1, 8], | |
[0, 0, 0, 0, 0, 0, 4, 5, 6], | |
[0, 0, 0, 0, 0, 0, 9, 7, 3] | |
] | |
SEED2 = [ | |
[3, 0, 0, 9, 0, 0, 0, 8, 0], | |
[0, 7, 4, 0, 3, 0, 0, 0, 0], | |
[0, 8, 0, 0, 6, 5, 1, 0, 0], | |
[0, 4, 0, 3, 1, 0, 0, 0, 0], | |
[0, 0, 0, 4, 9, 7, 0, 0, 0], | |
[7, 0, 9, 2, 0, 0, 0, 0, 3], | |
[4, 5, 7, 6, 2, 9, 0, 0, 8], | |
[6, 0, 0, 0, 8, 3, 0, 0, 0], | |
[0, 0, 0, 1, 0, 0, 0, 0, 6], | |
] | |
SEED3 = [ | |
[6, 0, 0, 0, 3, 0, 0, 0, 8], | |
[0, 8, 4, 0, 0, 7, 2, 0, 9], | |
[0, 0, 2, 5, 0, 0, 0, 0, 7], | |
[0, 0, 6, 0, 0, 0, 5, 0, 0], | |
[0, 0, 0, 0, 4, 1, 0, 8, 0], | |
[0, 0, 1, 0, 7, 0, 0, 0, 6], | |
[0, 0, 0, 0, 1, 6, 0, 0, 3], | |
[0, 0, 0, 0, 5, 0, 0, 4, 1], | |
[0, 6, 3, 4, 0, 2, 8, 0, 0], | |
] | |
b = Board.new(SEED3) | |
s = Solver.new(b) | |
s.board.display_puzzle | |
s.solve! | |
s.board.display_puzzle |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment