sudokusolver 1.3 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/sudokusolver.rb +36 -22
  2. metadata +2 -2
@@ -4,19 +4,20 @@
4
4
  # Algorithm, overall structure and original python source code by Peter Norvig
5
5
  # See http://norvig.com/sudoku.html
6
6
 
7
- ## Throughout this program:
8
- ## r is a row, e.g. 'A'
9
- ## c is a column, e.g. '3'
10
- ## s is a square, e.g. 'A3'
11
- ## d is a digit, e.g. '9'
12
- ## u is a unit, e.g. ['A1','B1','C1','D1','E1','F1','G1','H1','I1']
13
- ## g is a grid, e.g. 81 non-blank chars, e.g. starting with '.18...7...
14
- ## values is a hash of possible values, e.g. {'A1'=>'123489', 'A2'=>'8', ...}
7
+ # Throughout this program:
8
+ # r is a row, e.g. 'A'
9
+ # c is a column, e.g. '3'
10
+ # s is a square, e.g. 'A3'
11
+ # d is a digit, e.g. '9'
12
+ # u is a unit, e.g. ['A1','B1','C1','D1','E1','F1','G1','H1','I1']
13
+ # g is a grid, e.g. 81 non-blank chars, e.g. starting with '.18...7...
14
+ # values is a hash of possible values, e.g. {'A1'=>'123489', 'A2'=>'8', ...}
15
15
 
16
16
  class SudokuSolver
17
- VERSION = "1.3"
17
+ VERSION = "1.4"
18
18
  attr_reader :rows, :cols, :squares, :unitlist, :peers, :units
19
19
 
20
+ # Cross-product
20
21
  def cross(a, b)
21
22
  cp = Array.new # cross product
22
23
  a.each do |x|
@@ -60,6 +61,8 @@ class SudokuSolver
60
61
 
61
62
  end
62
63
 
64
+ # A grid is an 81 character string composed of the digits 0-9
65
+ # A blank is represented as a period.
63
66
  def parse_grid(g)
64
67
  g = g.chomp
65
68
  g = g.split('')
@@ -72,6 +75,9 @@ class SudokuSolver
72
75
  return values
73
76
  end
74
77
 
78
+ # Assign a value to a square in the Sudoku grid:
79
+ # Eliminate all other possible digits from the square
80
+ # by calling the eliminate function (mutually recursive)
75
81
  def assign(values, s, d)
76
82
  values[s].split('').each do |d2|
77
83
  unless d2 == d
@@ -81,19 +87,23 @@ class SudokuSolver
81
87
  return values
82
88
  end
83
89
 
90
+ # Remove a possibility from a square.
91
+ # Recursively propagate the constraints: look at the source code for how this is done.
84
92
  def eliminate(values, s, d)
85
93
  return values unless values[s].include?(d) ## Already eliminated.
86
94
 
87
- values[s] = values[s].sub(d,'') ## Remove the digit from the string of possibilities
88
- ## values[s].sub!(d,'') => why doesn't sub!() work?
95
+ values[s] = values[s].sub(d,'') # Remove the digit from the string of possibilities
96
+ # values[s].sub!(d,'') => why doesn't sub!() work?
89
97
 
90
- return false if values[s].length == 0 ## Contradiction: no more values (no more digits can be assigned)
98
+ return false if values[s].length == 0 # Contradiction: no more values (no more digits can be assigned)
91
99
 
92
- ## Remove digit from all peers
100
+ # Remove digit from all peers
101
+ # If the square has only one remaining possibility, that is the assigned value for the square and
102
+ # that value must be removed from all that square's peers.
93
103
  peers[s].each { |s2| return false unless eliminate(values, s2, values[s]) } if values[s].length == 1
94
104
 
95
- ## Assign digit if, by elimination, there is only one square left
96
- ## in the units for this square that can hold the digit
105
+ # Assign the digit to the square if, by elimination
106
+ # this is the only square that has the digit as a possibility
97
107
  units[s].each do |u|
98
108
  dplaces = Array.new
99
109
  u.each { |s2| dplaces << s2 if values[s2].include?(d) }
@@ -103,10 +113,11 @@ class SudokuSolver
103
113
  return values
104
114
  end
105
115
 
116
+ # Search if constraint satisfaction does not solve the puzzle
106
117
  def search(values)
107
118
  return false if values == false
108
119
 
109
- solved = true ## assumption
120
+ solved = true # assumption
110
121
  squares.each do |s|
111
122
  unless values[s].length == 1
112
123
  solved = false
@@ -117,7 +128,7 @@ class SudokuSolver
117
128
 
118
129
  min = 10
119
130
  start = nil
120
- squares.each do |s| ## Chose the undetermined square s with the fewest possibilities
131
+ squares.each do |s| # Chose the undetermined square s with the fewest possibilities
121
132
  l = values[s].length
122
133
  if l > 1 && l < min
123
134
  min = l
@@ -132,6 +143,7 @@ class SudokuSolver
132
143
  return false
133
144
  end
134
145
 
146
+ # Print a text Sudoku grid to STDOUT
135
147
  def print_grid(values)
136
148
  return if values == false
137
149
  max = 0
@@ -163,6 +175,7 @@ class SudokuSolver
163
175
  return values
164
176
  end
165
177
 
178
+ # Transform the solution into an 81 character string
166
179
  def string_solution(values)
167
180
  solution = ""
168
181
  squares.each do |s|
@@ -171,6 +184,7 @@ class SudokuSolver
171
184
  return solution
172
185
  end
173
186
 
187
+ # Verify the Sudoku solution
174
188
  def check_solution(solution)
175
189
  values = Hash.new
176
190
  for s,d in squares.zip(solution.split(''))
@@ -189,9 +203,9 @@ class SudokuSolver
189
203
 
190
204
  end
191
205
 
192
- ## Algorithm by Peter Norvig @ http://www.norvig.com/sudoku.html
206
+ # Algorithm by Peter Norvig @ http://www.norvig.com/sudoku.html
193
207
 
194
- ## More constraints:
195
- ## http://www.scanraid.com/BasicStrategies.htm
196
- ## http://www.krazydad.com/blog/2005/09/29/an-index-of-sudoku-strategies/
197
- ## http://www2.warwick.ac.uk/fac/sci/moac/currentstudents/peter_cock/python/sudoku/
208
+ # More constraints:
209
+ # http://www.scanraid.com/BasicStrategies.htm
210
+ # http://www.krazydad.com/blog/2005/09/29/an-index-of-sudoku-strategies/
211
+ # http://www2.warwick.ac.uk/fac/sci/moac/currentstudents/peter_cock/python/sudoku/
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: sudokusolver
5
5
  version: !ruby/object:Gem::Version
6
- version: "1.3"
7
- date: 2007-04-15 00:00:00 -04:00
6
+ version: "1.4"
7
+ date: 2007-04-22 00:00:00 -04:00
8
8
  summary: Commandline program and library for solving Sudoku puzzles
9
9
  require_paths:
10
10
  - lib