Class: Grid
- Inherits:
-
Object
- Object
- Grid
- Defined in:
- lib/sudoku_solver/grid.rb
Instance Attribute Summary collapse
-
#points ⇒ Object
Returns the value of attribute points.
-
#remaining_nums ⇒ Object
Returns the value of attribute remaining_nums.
Instance Method Summary collapse
- #all_naked_pairs ⇒ Object
- #box_count(box, num) ⇒ Object
- #box_line_reduction ⇒ Object
- #check_row(row, point, num, symbol) ⇒ Object
- #compare_points(arr) ⇒ Object
- #components ⇒ Object
- #fill_in ⇒ Object
- #fill_row(num) ⇒ Object
- #find_diff(point) ⇒ Object
- #flat_points ⇒ Object
- #flip(n) ⇒ Object
- #get_box(num) ⇒ Object
- #get_column(num) ⇒ Object
- #get_row(num) ⇒ Object
- #get_values(arr) ⇒ Object
- #hidden_pairs ⇒ Object
-
#initialize(txt_file) ⇒ Grid
constructor
A new instance of Grid.
- #is_solved? ⇒ Boolean
- #naked_pairs ⇒ Object
- #pinned_points ⇒ Object
- #pointing_pairs ⇒ Object
- #print_values ⇒ Object
- #print_values_formatted ⇒ Object
- #remaining_points ⇒ Object
- #solve ⇒ Object
- #update_points ⇒ Object
- #x_wing ⇒ Object
Constructor Details
#initialize(txt_file) ⇒ Grid
Returns a new instance of Grid.
6 7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/sudoku_solver/grid.rb', line 6 def initialize(txt_file) @points = [] txt_file.each_with_index do |text, row| text.split("").map(&:to_i).each_with_index do |num, col| @points << Point.new(row, col, num) end end remaining_points.each do |poi| poi.nums = Array(1..9) - (get_box(poi.box) + get_row(poi.y) + get_column(poi.x)) end end |
Instance Attribute Details
#points ⇒ Object
Returns the value of attribute points.
5 6 7 |
# File 'lib/sudoku_solver/grid.rb', line 5 def points @points end |
#remaining_nums ⇒ Object
Returns the value of attribute remaining_nums.
5 6 7 |
# File 'lib/sudoku_solver/grid.rb', line 5 def remaining_nums @remaining_nums end |
Instance Method Details
#all_naked_pairs ⇒ Object
108 109 110 111 112 |
# File 'lib/sudoku_solver/grid.rb', line 108 def all_naked_pairs fill_in pinned_points naked_pairs end |
#box_count(box, num) ⇒ Object
208 209 210 |
# File 'lib/sudoku_solver/grid.rb', line 208 def box_count(box, num) @points.select { |p| p.box == box && p.nums.to_set.subset?(num.to_set) }.count end |
#box_line_reduction ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/sudoku_solver/grid.rb', line 151 def box_line_reduction pointing_pairs remaining_points.each do |point| (1..9).each do |num| [:x, :y].each do |symbol| possible = remaining_points.select { |p| p.send(symbol) == point.send(symbol) && p.box == point.box && p.include?(num) } if possible.count >= 2 if @points.select { |p| p.send(symbol) == point.send(symbol) && (!possible.include?(p)) && p.include?(num) }.count == 0 remove = remaining_points.select { |p| p.box == point.box && p.include?(num) && (!possible.include?(p)) } remove.each do |r| r.nums = (r.nums - [num]) end end end end end end end |
#check_row(row, point, num, symbol) ⇒ Object
239 240 241 242 |
# File 'lib/sudoku_solver/grid.rb', line 239 def check_row(row, point, num, symbol) a = @points.select { |p| p.send(flip(symbol)) == row && p != point }.map { |x| x.nums }.flatten a.count(num) <= 1 end |
#compare_points(arr) ⇒ Object
182 183 184 185 186 187 188 |
# File 'lib/sudoku_solver/grid.rb', line 182 def compare_points(arr) a = [] a << :x if arr.all? { |w| w.x == arr.first.x } a << :y if arr.all? { |s| s.y == arr.first.y } a << :box if arr.all? { |t| t.box == arr.first.box } a end |
#components ⇒ Object
82 83 84 |
# File 'lib/sudoku_solver/grid.rb', line 82 def components [:x, :y, :box] end |
#fill_in ⇒ Object
71 72 73 74 75 |
# File 'lib/sudoku_solver/grid.rb', line 71 def fill_in remaining_points.each do |p| find_diff(p) end end |
#fill_row(num) ⇒ Object
44 45 46 |
# File 'lib/sudoku_solver/grid.rb', line 44 def fill_row(num) @points.select { |point| point.x == num } end |
#find_diff(point) ⇒ Object
48 49 50 |
# File 'lib/sudoku_solver/grid.rb', line 48 def find_diff(point) point.nums = point.nums - (get_box(point.box) + get_row(point.y) + get_column(point.x)) end |
#flat_points ⇒ Object
52 53 54 |
# File 'lib/sudoku_solver/grid.rb', line 52 def flat_points @points.select { |p| p.value == 0 } end |
#flip(n) ⇒ Object
244 245 246 247 248 249 250 |
# File 'lib/sudoku_solver/grid.rb', line 244 def flip(n) if n == :y :x else :y end end |
#get_box(num) ⇒ Object
32 33 34 |
# File 'lib/sudoku_solver/grid.rb', line 32 def get_box(num) @points.select { |point| point.box == num }.map { |b| b.value } end |
#get_column(num) ⇒ Object
40 41 42 |
# File 'lib/sudoku_solver/grid.rb', line 40 def get_column(num) @points.select { |point| point.x == num }.map { |b| b.value } end |
#get_row(num) ⇒ Object
36 37 38 |
# File 'lib/sudoku_solver/grid.rb', line 36 def get_row(num) @points.select { |point| point.y == num }.map { |b| b.value } end |
#get_values(arr) ⇒ Object
56 57 58 |
# File 'lib/sudoku_solver/grid.rb', line 56 def get_values(arr) arr.map { |b| b.value } end |
#hidden_pairs ⇒ Object
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/sudoku_solver/grid.rb', line 191 def hidden_pairs all_naked_pairs remaining_points.each do |point| next if point.nums.count <= 1 point.nums.combination(2).each do |arr| components.each do |symbol| remove = @points.select { |p| p.send(symbol) == point.send(symbol) && arr.to_set.subset?(p.nums.to_set) && p.nums.count >= 2} if remove.count == 2 && @points.select { |p| p.send(symbol) == point.send(symbol) && ( arr.include?(p.value)) }.count == 0 #remove.each { |r| r.nums = arr } return end end end end end |
#is_solved? ⇒ Boolean
170 171 172 |
# File 'lib/sudoku_solver/grid.rb', line 170 def is_solved? @points.select{ |p| p.value == 0 }.count == 0 end |
#naked_pairs ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/sudoku_solver/grid.rb', line 114 def naked_pairs remaining_points.each do |point| next if point.nums.count <= 1 components.each do |symbol| possible = remaining_points.select { |p| p.subset?(point) && p != point && p.send(symbol) == point.send(symbol) && p.nums.count >= 2 } possible << point if possible.count == point.nums.count compare_points(possible).each do |type| found = remaining_points.select { |p| p.send(type) == point.send(type) && (!possible.include?(p)) } found.each do |f| f.nums = (f.nums - point.nums) end end end end end end |
#pinned_points ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/sudoku_solver/grid.rb', line 86 def pinned_points remaining_points.each do |point| components.each do |symbol| point.nums.each do |num| if @points.select { |p| p.include?(num) && p.send(symbol) == point.send(symbol) && p != point }.count == 0 point.value = num end end end end end |
#pointing_pairs ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/sudoku_solver/grid.rb', line 132 def pointing_pairs all_naked_pairs remaining_points.each do |point| (1..9).each do |num| [:x, :y].each do |symbol| possible = @points.select { |p| p.send(symbol) == point.send(symbol) && p.box == point.box && p.include?(num) } if possible.count >= 2 if @points.select { |p| p.box == point.box && (!possible.include?(p)) && p.include?(num) }.count == 0 remove = remaining_points.select { |p| p.box != point.box && p.send(symbol) == point.send(symbol) && p.include?(num) } remove.each do |r| r.nums = (r.nums - [num]) end end end end end end end |
#print_values ⇒ Object
26 27 28 29 30 |
# File 'lib/sudoku_solver/grid.rb', line 26 def print_values a = @points.map { |p| p.value}.join puts a a end |
#print_values_formatted ⇒ Object
19 20 21 22 23 24 |
# File 'lib/sudoku_solver/grid.rb', line 19 def print_values_formatted puts "SOLUTION" @points.each_slice(9) do |s| puts s.map{ |p| p.value}.join end end |
#remaining_points ⇒ Object
78 79 80 |
# File 'lib/sudoku_solver/grid.rb', line 78 def remaining_points @points.select { |p| p.value == 0 } end |
#solve ⇒ Object
98 99 100 101 102 103 104 105 106 |
# File 'lib/sudoku_solver/grid.rb', line 98 def solve while !is_solved? all_naked_pairs hidden_pairs pointing_pairs box_line_reduction x_wing end end |
#update_points ⇒ Object
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/sudoku_solver/grid.rb', line 60 def update_points @points.select { |po| po.value == 0 }.each do |poi| find_diff(poi) end (0..8).each do |num| [:box, :x, :y].each do |fields| yield @points.select { |p| p.send(fields) == num } end end end |
#x_wing ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/sudoku_solver/grid.rb', line 212 def x_wing box_line_reduction remaining_points.each do |point| point.nums.each do |num| [:x, :y].each do |symbol| arr = @points.select{ |p| p.nums.include?(num) && p.send(flip(symbol)) == point.send(flip(symbol)) && p.value == 0 } if arr.count == 2 && @points.select { |p| p.value == num && p.send(flip(symbol)) == point.send(flip(symbol)) }.count == 0 last = @points.select { |p| p.nums.include?(num) && arr.map{ |a| a.send(symbol) }.include?(p.send(symbol)) && (!arr.include?(p)) && p.value == 0 && check_row(p.y,p,num,symbol) } if last.all? { |x| x.send(flip(symbol)) == last.first.send(flip(symbol)) } && last.count == 2 && @points.select { |p| p.value == num && p.send(flip(symbol)) == last.first.send(flip(symbol)) }.count == 0 final = arr + last places = final.map { |m| m.send(symbol) }.uniq remaining_points.select { |p| places.include?(p.send(symbol)) && (!final.include?(p)) }.each do |poi| poi.nums = poi.nums - [num] end end end end end end end |