rubyで数独 実装
前回のrubyで数独の本を参考に実装したもの。
自分が読みやすいように書き換えたり、クラスを導入したりした。
Sudoku_conditionクラスの中身は読むのすら面倒だったから本の内容そのまま。
ここ読むだけでもこの本のコードがどのくらい読みにくいかわかると思う。
class Sudoku def initialize @condition = Sudoku_condition.new end def solve(string) grid_new = make_grid(string) grid_solved = solve_sub(grid_new, 0) print_grid(grid_solved) end private def solve_sub(grid, p) #pは現在のセル番号 return true if p > 80 print_debug(grid,p) #過程を見るため if grid[p] solve_sub(grid, p + 1) else for v in 1..9 grid[p] = v return true if @condition.no_violation?(grid, p) && solve_sub(grid, p + 1) end grid[p] = nil #1〜9まで試してどれもダメだったら return false end end def make_grid(string) string.gsub!(/[\s\n]/, '') string.split("").map { |num_c| num_c == "." ? nil : num_c.to_i } end def print_grid(grid) grid.each_slice(9).map do |arr| puts arr.join(" ") end end def print_debug(grid,p) print_grid(grid) puts "-------------------- #{p}" sleep(0.05) #ゆっくりみるため end end class Sudoku_condition def initialize end def no_violation?(grid, p) (block_is_ok?(row(grid, p)) && block_is_ok?(column(grid, p)) && block_is_ok?(square(grid, p))) end private def row(grid, p) grid[9 * (p / 9), 9] end def column(grid, p) (0..8).map { |k| grid[9 * k + p % 9] } end def square(grid, p) (0..8).map { |k| grid[9 * (3 * (p / 9 / 3) + (k / 3)) + 3 * (p % 9 / 3) + (k % 3)] } end def block_is_ok?(block) unique?(block.compact) end def unique?(list) (list.length == list.uniq.length) end end line = "61....... .......27 4..6.8... .71...3.. 2385.6419 9641..75. 395.278.. 182.6.974 .468192.5" sudoku = Sudoku.new sudoku.solve(line)