class Variable def initialize(domain) @domain = domain end def fixed? if @domain.length == 1 @domain[0] else false end end def include?(x) @domain.include?(x) end def fix(x) @domain = [x] end def eliminate(x) @domain.delete(x) unless fixed? end end def sudokuprint(grid, subsize, size = subsize * subsize) w = Math.log10(size).ceil bar = '┼ ┼' + (('─' * (subsize * (w + 1) + 1) + '┼') * subsize + ' ┼') * subsize puts bar puts bar (0...size).step(subsize).each do |rs| (rs...(rs + subsize)).each do |r| (1..size).step(subsize).each do |ds| print '│ │ ' (0...size).step(subsize).each do |b| (b...(b + subsize)).each do |c| (ds...(ds + subsize)).each do |d| print (grid[r][c].include?(d) ? ("%#{w}d" % d) : (' ' * w)) + ' ' end print '│ ' end print '│ ' end puts end puts bar end puts bar end end SUBSIZE = 3 SIZE = SUBSIZE * SUBSIZE boxes = [] (0...SIZE).step(SUBSIZE).each do |r| (0...SIZE).step(SUBSIZE).each do |c| boxes.push([r, c]) end end grid = Array.new(SIZE) { Array.new(SIZE) { Variable.new((1..SIZE).to_a) } } grid[0][3].fix(2) grid[0][4].fix(9) grid[0][5].fix(4) grid[0][6].fix(3) grid[0][8].fix(5) grid[1][0].fix(9) grid[1][1].fix(5) grid[1][3].fix(6) grid[1][5].fix(8) grid[1][6].fix(7) grid[1][8].fix(2) grid[2][2].fix(3) grid[2][7].fix(8) grid[3][1].fix(8) grid[3][8].fix(4) grid[4][1].fix(6) grid[4][3].fix(9) grid[4][5].fix(1) grid[4][7].fix(7) grid[5][0].fix(4) grid[5][7].fix(5) grid[6][1].fix(1) grid[6][6].fix(2) grid[7][0].fix(2) grid[7][2].fix(6) grid[7][3].fix(5) grid[7][5].fix(3) grid[7][7].fix(9) grid[7][8].fix(8) grid[8][0].fix(3) grid[8][2].fix(7) grid[8][3].fix(1) grid[8][4].fix(8) grid[8][5].fix(2) until grid.flatten.count(&:fixed?) == 81 (0...SIZE).each do |i| row = grid[i] row.each do |cell| if v = cell.fixed? row.each do |c2| c2.eliminate(v) end end end end (0...SIZE).each do |i| col = grid.map { |row| row[i] } col.each do |cell| if v = cell.fixed? col.each do |c2| c2.eliminate(v) end end end end (0...SIZE).each do |i| rs, cs = boxes[i] box = [] (rs...(rs + SUBSIZE)).each do |r| (cs...(cs + SUBSIZE)).each do |c| box.push(grid[r][c]) end end box.each do |cell| if v = cell.fixed? box.each do |c2| c2.eliminate(v) end end end end end sudokuprint(grid, SUBSIZE, SIZE)