doku 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,23 +43,23 @@ This gem is designed to solve Sudoku-like puzzles. For the purposes of this gem
43
43
 
44
44
  For example, in Sudoku, the glyphs are the numbers 0 through 9, the squares are the squares of a 9x9 grid, and the groups consist of nine rows, nine columns, and nine 3x3 squares.
45
45
 
46
- Every Sudoku-like puzzle can be reduced to an {exact cover problem}[http://en.wikipedia.org/wiki/Exact_cover]. From there is can be efficiently solved with the {Dancing Links}[http://arxiv.org/abs/cs/0011047] algorithm discovered by Donald Knuth. That is the main purpose of this gem.
46
+ Every Sudoku-like puzzle can be reduced to an {exact cover problem}[http://en.wikipedia.org/wiki/Exact_cover]. From there it can be efficiently solved with the {Dancing Links}[http://arxiv.org/abs/cs/0011047] algorithm discovered by Donald Knuth. That is the main purpose of this gem.
47
47
 
48
48
  == Classes and Modules Overview
49
49
 
50
- The Doku::Puzzle class is an abstract class for working with Sudoku-like puzzles. It implements the concepts of groups, glyphs and squares. Each instance of this class represents a particular assignment of glyphs to squares; at its core, an instance is just a hash where the keys are squares and values are glyphs. This class provides <code>[]</code> and <code>[]=</code> methods for reading and modifying instances of the puzzle. It provides equality comparison and solution checking.
50
+ The <b>Doku::DancingLinks</b> module contains several classes that comprise a general-purpose implementation of the Dancing Links algorithm. This module is included in the Doku gem for convenience, but it is not specifically for solving Sudoku-like puzzles; it can be applied to any exact cover problem.
51
51
 
52
- The Puzzle class includes the Doku::SolvableWithDancingLinks module which provides methods for solving puzzles using the Dancing Links algorithm. The solutions returned are instances of Puzzle.
52
+ The <b>Doku::Puzzle</b> class is an abstract class for working with Sudoku-like puzzles. It implements the concepts of groups, glyphs and squares. Each instance of this class represents a particular assignment of glyphs to squares; at its core, an instance is just a hash where the keys are squares and the values are glyphs. This class provides <code>[]</code> and <code>[]=</code> methods for reading and modifying instances of the puzzle, and it makes <code>dup</code> and <code>clone</code> work correctly. This class provides equality comparison and solution checking.
53
53
 
54
- The Doku::SquareOnGrid module provides methods used for Sudoku-like puzzles that can be drawn on a 2D grid. It implements the string representations of the puzzle by providing an <code>initialize</code> method that creates puzzles from strings and a <code>to_s</code> method that creates strings from puzzles. It provides <code>get</code> and <code>set</code> methods for modifying suqares of the puzzle by their coordinates.
54
+ The Puzzle class includes the <b>Doku::SolvableWithDancingLinks</b> module which provides methods for solving puzzles using Doku::DancingLinks. The solutions returned are instances of Puzzle. This module is the glue that connects Doku::Puzzle to Doku::DancingLinks.
55
55
 
56
- The classes Doku::Sudoku, Doku::Hexadoku, and Doku::Hexamurai all inherit from Doku::Puzzle and include Doku::SquareOnGrid. Because of the framework set up by that class and that module, the definitions of these classes are short and the methods provided by each of them are rich and consistent with eachother.
56
+ The <b>Doku::SquareOnGrid</b> module is useful for any Sudoku-like puzzle that can be drawn on a 2D grid. It implements the string representations of the puzzle by providing an <code>initialize</code> method that creates puzzles from strings and a <code>to_s</code> method that creates strings from puzzles. It also provides convenient <code>get</code> and <code>set</code> methods for reading and modifying instances of the puzzle using grid coordinates.
57
57
 
58
- The Doku::DancingLinks module contains several class that comprise a general-purpose implementation of the Dancing Links algorithm. This module is included in the Doku gem for convenience, but it is not specifically for solving Sudoku-like puzzles; it can be applied to any exact cover problem.
58
+ The classes <b>Doku::Sudoku</b>, <b>Doku::Hexadoku</b>, and <b>Doku::Hexamurai</b> all inherit from Doku::Puzzle and include Doku::SquareOnGrid. As a user of the gem, these are the classes you will probably interact with most of the time. Because of the framework set up by Doku::Puzzle and include Doku::SquareOnGrid, the definitions of these classes are short and the methods provided by each of them are rich and consistent with eachother.
59
59
 
60
60
  == Detailed Documentation
61
61
 
62
- For detailed documentation of every class, module, and method, see the "Class List" link above.
62
+ For detailed documentation of every class, module, and method go to the {rubydoc.info page}[http://rubydoc.info/github/DavidEGrayson/doku/master/frames] and look for the Class List.
63
63
 
64
64
  == Contributing
65
65
 
@@ -74,6 +74,8 @@ There are many directions this gem could go in. The direction will be determine
74
74
  * More types of puzzles that are solvable (e.g. puzzles that have groups with fewer squares than the number of glyphs).
75
75
  * Improve this page. Ideally the method names should be linkified on the {rubydoc.info page}[http://rubydoc.info/github/DavidEGrayson/doku/master], but I still want something presentable to be on the {github repository}[https://github.com/DavidEGrayson/doku]. Here's an example of a link that looks good on RubyDoc.info but not on github: {Doku::Sudoku Sudoku}. If either YARD or Github could be configured to use a different file on the front page, that would suffice!
76
76
 
77
+ To report bugs, use the {github issues page}[https://github.com/DavidEGrayson/doku/issues].
78
+
77
79
  == Philosophy
78
80
 
79
81
  This gem is meant to showcase beautiful Ruby code. Test-driven development was used at all times during the development of this gem. I have spent many hours reviewing the code, looking for ways to make it simpler, and refactoring it. Every class and public method is documented. Every method is short. There are no ugly hacks. All method names were chosen carefully. At every level, the power of the Ruby language is exploited to its fullest potential. --David Grayson
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.1
1
+ 1.1.0
@@ -250,19 +250,29 @@ module Doku::DancingLinks
250
250
  alias :nodes :nodes_rightward
251
251
 
252
252
  # Removes a row from the {LinkMatrix} by covering every
253
- # column that it touches. This represents (tentatively)
253
+ # column that it touches.
254
+ def choose
255
+ nodes_rightward.each do |node|
256
+ node.column.cover
257
+ end
258
+ end
259
+
260
+ # Removes a row from the {LinkMatrix} by covering every
261
+ # column that it touches EXCEPT self.column, which is
262
+ # assumed to already be covered.
263
+ # This represents (tentatively)
254
264
  # choosing the node's row to be in our exact cover.
255
265
  # When that choice is proven to not work, this action can
256
- # be efficiently undone with {#unchoose}.
257
- def choose
266
+ # be efficiently undone with {#unchoose_except_self_column}.
267
+ def choose_except_self_column
258
268
  nodes_except_self_rightward.each do |node|
259
269
  node.column.cover
260
270
  end
261
271
  end
262
272
 
263
- # Undoes the effect of {#choose}, putting
273
+ # Undoes the effect of {#choose_except_self_column}, putting
264
274
  # the nodes of the row back into the {LinkMatrix}.
265
- def unchoose
275
+ def unchoose_except_self_column
266
276
  nodes_except_self_leftward.each do |node|
267
277
  node.column.uncover
268
278
  end
@@ -366,7 +376,7 @@ module Doku::DancingLinks
366
376
  # as a new column.
367
377
  #
368
378
  # @param column_ids (Enumerable) The column_ids that are in this row.
369
- # @param row_id (Object) The id of this row. This is used to express express exact covers and as the argument to {#remove_row}.
379
+ # @param row_id (Object) The id of this row. This is used to express express exact covers.
370
380
  def add_row(column_ids, row_id=column_ids.dup)
371
381
  first_node = nil
372
382
  column_ids = column_ids.uniq if column_ids.respond_to?(:uniq)
@@ -390,16 +400,6 @@ module Doku::DancingLinks
390
400
  end
391
401
  end
392
402
 
393
- # Removes a row from the matrix.
394
- # @param row_id (Object) The ID of the row that was specified when
395
- # {#add_row} was called.
396
- def remove_row(row_id)
397
- raise ArgumentError, "Row with id #{row_id} not found." if !@rows[row_id]
398
- @rows[row_id].nodes_rightward.each do |node|
399
- node.column.cover
400
- end
401
- end
402
-
403
403
  # Retrieves a node in the row with the specified ID or returns nil if there is
404
404
  # no row with that ID.
405
405
  # @param id (Object) The ID of the row that was specified when
@@ -493,7 +493,7 @@ module Doku::DancingLinks
493
493
 
494
494
  # Try the node (push it and cover its columns).
495
495
  nodes.push node
496
- node.choose
496
+ node.choose_except_self_column
497
497
 
498
498
  end
499
499
  end
@@ -538,7 +538,7 @@ module Doku::DancingLinks
538
538
  # We tried nodes.last and it didn't work, so
539
539
  # pop it off and uncover the corresponding columns.
540
540
  node = nodes.pop
541
- node.unchoose
541
+ node.unchoose_except_self_column
542
542
 
543
543
  # Try the next node in this column.
544
544
  x = node.down
@@ -38,13 +38,14 @@ module Doku
38
38
  # @return (DancingLinks::LinkMatrix)
39
39
  def to_link_matrix
40
40
  # Create the link matrix. This is a generic matrix
41
- # that does not take in to account square.given_glyph.
41
+ # that does not take in to account the state of this instance.
42
42
  sm = DancingLinks::LinkMatrix.from_sets sets_for_exact_cover_problem
43
43
 
44
- # Take into account square.given_glyph by covering certain
45
- # rows (removing the row and all columns it touches).
44
+ # Take into account the state of this instance
45
+ # by "choosing" rows. This removes them from the matrix
46
+ # by covering all the columns they touch.
46
47
  each do |square, glyph|
47
- sm.remove_row SquareAndGlyph.new(square,glyph)
48
+ sm.row(SquareAndGlyph.new(square,glyph)).choose
48
49
  end
49
50
 
50
51
  sm
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doku
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-27 00:00:00.000000000 Z
12
+ date: 2012-02-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: backports
16
- requirement: &12242900 !ruby/object:Gem::Requirement
16
+ requirement: &23796760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *12242900
24
+ version_requirements: *23796760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &12241680 !ruby/object:Gem::Requirement
27
+ requirement: &23796140 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *12241680
35
+ version_requirements: *23796140
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bundler
38
- requirement: &12240840 !ruby/object:Gem::Requirement
38
+ requirement: &23795460 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *12240840
46
+ version_requirements: *23795460
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: jeweler
49
- requirement: &12256480 !ruby/object:Gem::Requirement
49
+ requirement: &23811100 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.6.2
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *12256480
57
+ version_requirements: *23811100
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rcov
60
- requirement: &12255860 !ruby/object:Gem::Requirement
60
+ requirement: &23810380 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *12255860
68
+ version_requirements: *23810380
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
- requirement: &12255300 !ruby/object:Gem::Requirement
71
+ requirement: &23809620 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *12255300
79
+ version_requirements: *23809620
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: watchr
82
- requirement: &12253280 !ruby/object:Gem::Requirement
82
+ requirement: &23808740 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *12253280
90
+ version_requirements: *23808740
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: ruby-prof
93
- requirement: &12251880 !ruby/object:Gem::Requirement
93
+ requirement: &23805220 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *12251880
101
+ version_requirements: *23805220
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: linecache19
104
- requirement: &12250680 !ruby/object:Gem::Requirement
104
+ requirement: &23812680 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *12250680
112
+ version_requirements: *23812680
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ruby-debug-base19
115
- requirement: &12249640 !ruby/object:Gem::Requirement
115
+ requirement: &23852140 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 0.11.26
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *12249640
123
+ version_requirements: *23852140
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: ruby-debug19
126
- requirement: &12264740 !ruby/object:Gem::Requirement
126
+ requirement: &23851580 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *12264740
134
+ version_requirements: *23851580
135
135
  description: ! 'This gem allows you to represent Sudoku-like puzzles
136
136
 
137
137
  (Sudoku, Hexadoku, and Hexamurai) as objects and find