Class: Xudoku::Board
Overview
Represents a Sudoku board as a flat array of 81 cell values.
Values are stored as zero-based integers (0–8) internally, where nil denotes an empty cell. All factory methods accept one-based input (1–9) and convert automatically.
Boards can be constructed via Board.from_string, Board.from_array, or from_empty, and serialised back via to_s, to_a, or to_json.
Class Method Summary collapse
-
.empty {|board, value, index| ... } ⇒ Board
Creates a new empty board, optionally populated via a block.
-
.from_array(array) ⇒ Board
Creates a new board instance from an array of cell values.
-
.from_string(board_string) ⇒ Board
Creates a new board instance by parsing a formatted board string.
Instance Method Summary collapse
- #deduce ⇒ Object
- #missing_from_axis(x, axis) ⇒ Object
- #numbers_missing ⇒ Object
- #to_a ⇒ Object
- #to_json(*_args) ⇒ Object
- #to_s ⇒ Object
-
#value_at(x, y, axis) ⇒ Object
:stopdoc:.
Methods included from Utils
#bits_to_numbers, #guesses_from, #pick_better, #pos
Class Method Details
.empty {|board, value, index| ... } ⇒ Board
Creates a new empty board, optionally populated via a block.
Without a block, returns a board with all 81 cells set to nil. When a block is given, each cell is yielded in order and set to the block’s return value, allowing custom initialisation logic.
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/xudoku/board.rb', line 102 def self.empty board = new(81.times.map { nil }) return board unless block_given? board.each_with_index do |value, index| board[index] = yield(board, value, index) end board end |
.from_array(array) ⇒ Board
Creates a new board instance from an array of cell values.
Accepts either a flat array or a nested array of rows, which is automatically flattened. Values are converted to zero-based indices, and nil entries are preserved as empty cells.
75 76 77 78 |
# File 'lib/xudoku/board.rb', line 75 def self.from_array(array) array = array.flatten if array.first.is_a?(Array) new(array.map { |i| i.nil? ? i : i - 1 }) end |
.from_string(board_string) ⇒ Board
Creates a new board instance by parsing a formatted board string.
Scans the string token by token, ignoring border characters (- + | =), and collects up to 81 cell values. Digit characters are converted to zero-based values (so "1" becomes 0, "9" becomes 8, and non-digit tokens are treated as empty cells).
41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/xudoku/board.rb', line 41 def self.from_string(board_string) result = [] board_string.split.each do |char| next if char.match?(/[-+|=]/) result << (char.to_i - 1 if char.match?(/\d/)) break if result.size == 81 end new(result) end |
Instance Method Details
#deduce ⇒ Object
119 120 121 |
# File 'lib/xudoku/board.rb', line 119 def deduce Deducer.new(self).deduce end |
#missing_from_axis(x, axis) ⇒ Object
123 124 125 126 127 128 129 130 131 |
# File 'lib/xudoku/board.rb', line 123 def missing_from_axis(x, axis) bits = 0 9.times do |y| value = value_at(x, y, axis) bits |= (1 << value) unless value.nil? end 511 ^ bits end |
#numbers_missing ⇒ Object
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/xudoku/board.rb', line 133 def numbers_missing allowed = 81.times.map do |x| if self[x].nil? 511 else 0 end end needed = [] [0, 1, 2].each do |axis| 9.times do |x| bits = missing_from_axis(x, axis) needed << bits 9.times do |y| allowed[pos(x, y, axis)] &= bits end end end [allowed, needed] end |
#to_a ⇒ Object
156 157 158 |
# File 'lib/xudoku/board.rb', line 156 def to_a Formatter::Array.new(self).format end |
#to_json(*_args) ⇒ Object
164 165 166 |
# File 'lib/xudoku/board.rb', line 164 def to_json(*_args) Formatter::JSON.new(self).format end |
#to_s ⇒ Object
160 161 162 |
# File 'lib/xudoku/board.rb', line 160 def to_s Formatter::String.new(self).format end |
#value_at(x, y, axis) ⇒ Object
:stopdoc:
115 116 117 |
# File 'lib/xudoku/board.rb', line 115 def value_at(x, y, axis) self[pos(x, y, axis)] end |