dancing-links 0.1.0.1 → 0.1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/Rakefile +32 -21
  2. data/test/tc_dancing_links.rb +222 -0
  3. metadata +12 -9
data/Rakefile CHANGED
@@ -1,24 +1,13 @@
1
1
  require 'rubygems'
2
2
  require 'rubygems/package_task'
3
+ require 'rake/testtask'
3
4
  require 'rdoc/task'
4
5
 
5
- task :default => [:rdoc, :gem]
6
-
7
- PKG_FILES = FileList['lib/**/*.rb','[A-Z]*']
8
-
9
- gem_spec = Gem::Specification.new do |s|
10
- s.platform = Gem::Platform::RUBY
11
- s.summary = 'An implementation of "Dancing Links".'
12
- s.name = "dancing-links"
13
- s.version = "0.1.0.1"
14
- s.authors = ["Justin W Smith"]
15
- s.require_path = 'lib'
16
- s.email = 'justin dot w dot smith @t gmail.com'
17
- s.files = PKG_FILES
18
- s.homepage = 'https://rubygems.org/gems/dancing-links'
19
- s.has_rdoc = true
20
- s.rubyforge_project = 'sudoku-gtk'
21
- s.description = 'An implementation of the "dancing links" algorithm to solve the "exact cover" problem.'
6
+ task :default => [:test]
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.test_files = ['test/tc_dancing_links.rb']
10
+ t.verbose = true
22
11
  end
23
12
 
24
13
  Rake::RDocTask.new do |rd|
@@ -27,8 +16,30 @@ Rake::RDocTask.new do |rd|
27
16
  end
28
17
 
29
18
 
30
- Gem::PackageTask.new(gem_spec) do |t|
31
- t.need_zip = true
32
- t.need_tar = true
33
- end
19
+ PKG_FILES = FileList['lib/**/*.rb','[A-Z]*']
20
+ TEST_FILES = FileList['test/**/*.rb']
21
+
22
+ gem_spec = Gem::Specification.new do |s|
23
+ s.platform = Gem::Platform::RUBY
24
+ s.summary = 'Implementation of the "Dancing Links" algorithm.'
25
+ s.name = 'dancing-links'
26
+ s.email = 'justin dot w dot smith at gmail dot com'
27
+ s.authors = ['Justin W Smith']
28
+ s.homepage = 'http://rubyforge.org/projects/sudoku-gtk/'
29
+ s.version = '0.1.0.2'
30
+ s.requirements << 'none'
31
+ s.require_path = 'lib'
32
+ s.files = PKG_FILES
33
+ s.test_files = TEST_FILES
34
+ s.has_rdoc = true
35
+ s.description = <<EOF
36
+ Dancing-links is an implementation of the "Dancing Links" algorthm to solve the
37
+ "Exact Cover" problem. Algorithm found by Donald Knuth.
38
+ EOF
39
+ end
40
+
41
+ Gem::PackageTask.new(gem_spec) do |t|
42
+ t.need_zip = true
43
+ t.need_tar = true
44
+ end
34
45
 
@@ -0,0 +1,222 @@
1
+
2
+ # Copyright (c) 2006 Justin W Smith
3
+
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this
5
+ # software and associated documentation files (the "Software"), to deal in the Software
6
+ # without restriction, including without limitation the rights to use, copy, modify,
7
+ # merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to the following
9
+ # conditions:
10
+
11
+ # The above copyright notice and this permission notice shall be included in all copies
12
+ # or substantial portions of the Software.
13
+
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16
+ # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+
21
+
22
+ require 'test/unit'
23
+ require 'dancing_links'
24
+
25
+ class Array
26
+ def to_s
27
+ s = "["
28
+ each_index do |i|
29
+ s << " " + self[i].to_s
30
+ s << ", " unless (i == self.length-1)
31
+ end
32
+ s << "]"
33
+ end
34
+
35
+ def comb_helper head, tail, &block
36
+ if tail.length == 0
37
+ block.call(head)
38
+ else
39
+ tail.each_index do |i|
40
+ t = tail.clone
41
+ t.delete_at(i)
42
+ comb_helper head.clone << tail[i], t, &block
43
+ end
44
+ end
45
+ end
46
+
47
+ def combinations &block
48
+ comb_helper [], self, &block
49
+ end
50
+ end
51
+
52
+ class TC_DancingLinks < Test::Unit::TestCase
53
+ include DancingLinks
54
+
55
+ def setup
56
+ @a1 = [ [1, 0, 1], [0, 0, 1], [1, 1, 0], [ 1, 0, 0] ]
57
+ @b1 = [ [ true, false, true],
58
+ [false, false, true],
59
+ [true, true, false],
60
+ [true, false, false] ]
61
+ @matrix1 = SparseMatrix.new convert_rows_fixnum_to_boolean(@a1)
62
+ @s1 = [ [ 0, 0, 1], [ 1, 1, 0] ]
63
+
64
+ @a2 = [ [1, 0, 1], [1, 1, 0], [0, 1, 1], [ 0, 0, 0] ]
65
+ @e2 = [ [0, 0, 1] ]
66
+ @matrix2 = SparseMatrix.new convert_rows_fixnum_to_boolean(@a2)
67
+ @s2 = [ [0, 0, 1], [ 1, 1, 0] ]
68
+
69
+ @a3 = [ [1, 0, 1], [1, 1, 0], [0, 1, 1], [ 1, 1, 1] ]
70
+ @matrix3 = SparseMatrix.new convert_rows_fixnum_to_boolean(@a3)
71
+ @s3 = [[1, 1, 1]]
72
+
73
+ @a4 = [ [1, 0, 1], [1, 1, 0], [0, 1, 1], [ 0, 1, 0] ]
74
+ @matrix4 = SparseMatrix.new convert_rows_fixnum_to_boolean(@a4)
75
+ @s4 = [[1, 0, 1], [0, 1, 0]]
76
+
77
+ @a5 = [ [1, 0, 1], [1, 1, 0], [1, 1, 1], [ 0, 1, 1] ]
78
+ @matrix5 = SparseMatrix.new convert_rows_fixnum_to_boolean(@a4)
79
+ @s5 = [[1, 1, 1]]
80
+
81
+ @a6 = [ [1, 0, 1], [1, 0, 0], [1, 1, 1], [ 0, 1, 1], [1, 1, 0] ]
82
+
83
+ @a7 = [ [0, 0, 1], [ 0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1] ]
84
+ @s7 = [
85
+ [ [ 1, 1, 1] ],
86
+ [ [ 0, 1, 1], [ 1, 0, 0 ] ].sort,
87
+ [ [ 1, 0, 1], [ 0, 1, 0 ] ].sort,
88
+ [ [ 1, 1, 0], [ 0, 0, 1] ].sort,
89
+ [ [ 0, 0, 1], [0, 1, 0], [1, 0, 0] ].sort ]
90
+ end
91
+
92
+ def test_convert_rows
93
+ assert_equal(@a1, convert_rows_boolean_to_fixnum(@b1) )
94
+ assert_equal(@b1, convert_rows_fixnum_to_boolean(@a1) )
95
+ end
96
+
97
+ def test_sparse_matrix
98
+ root = @matrix1.root
99
+ assert_equal(3, root.count)
100
+ assert_equal(3, root.right.count)
101
+ assert_equal(1, root.right.right.count)
102
+ assert_equal(2, root.right.right.right.count)
103
+ assert_equal(root.right.up.left, root.right.up)
104
+ assert_equal(root.left.up.left, root.right.right.right.down.down)
105
+ assert_equal(root.right.down.header, root.right)
106
+ assert_equal(root.left.up.header, root.left)
107
+ assert_equal(root.right.right.right.right, root)
108
+ assert_equal(root.left.left.left.left, root)
109
+
110
+ assert_equal(0, root.left.down.row_num)
111
+ assert_equal(1, root.left.down.down.row_num)
112
+ assert_equal(2, root.right.right.down.row_num)
113
+ assert_equal(3, root.right.up.row_num)
114
+
115
+ assert_equal(0, root.right.index)
116
+ assert_equal(3, root.right.count)
117
+ assert_equal(1, root.right.right.index)
118
+ assert_equal(1, root.right.right.count)
119
+ assert_equal(2, root.right.right.right.index)
120
+ assert_equal(2, root.right.right.right.count)
121
+
122
+ end
123
+
124
+ def test_remove_rows_for_header
125
+ root = @matrix1.root
126
+ remove_rows_for_header root.right
127
+ assert_equal( 0, root.right.count)
128
+ assert_equal( 0, root.right.right.count)
129
+ assert_equal( 1, root.right.right.right.count)
130
+ assert_equal( root.right.right.right, root.left)
131
+ assert_equal( root.left.down, root.right.right.right.up)
132
+ assert_equal( 1, root.left.down.row_num)
133
+ end
134
+
135
+ def test_restore_rows_for_header
136
+ root = @matrix1.root
137
+ restore_rows_for_header( remove_rows_for_header( root.right))
138
+ test_sparse_matrix
139
+ end
140
+
141
+ def test_select_row
142
+ root = @matrix1.root
143
+ header_stk, row_stk_stk = select_row root.right.right.down
144
+
145
+ assert_equal( 1, root.count)
146
+ assert_equal( 1, root.right.count)
147
+ assert_equal( 2, root.right.index )
148
+ assert_equal( root.right.down, root.left.down)
149
+ assert_equal( root.right.down.down, root.left)
150
+ assert_equal( root.right.down.down, root.left)
151
+
152
+ end
153
+
154
+ def test_restore_selected_row
155
+
156
+ root = @matrix1.root
157
+ restore_selected_row( *select_row( root.right.right.down))
158
+ test_sparse_matrix
159
+ restore_selected_row( *select_row( root.right.down))
160
+ test_sparse_matrix
161
+ restore_selected_row( *select_row( root.left.down))
162
+ test_sparse_matrix
163
+ restore_selected_row( *select_row( root.left.up))
164
+ test_sparse_matrix
165
+ restore_selected_row( *select_row( root.right.up))
166
+ test_sparse_matrix
167
+ restore_selected_row( *select_row( root.left.up))
168
+ test_sparse_matrix
169
+
170
+ header_stk, row_stk_stk = select_row( root.right.right.down)
171
+ restore_selected_row( *select_row( root.right.down) )
172
+ restore_selected_row( header_stk, row_stk_stk)
173
+ test_sparse_matrix
174
+
175
+ end
176
+
177
+ def test_min_column
178
+ root = @matrix1.root
179
+ header = min_column root
180
+ assert_equal( root.right.right, header)
181
+ end
182
+
183
+ def test_solve_exact_cover
184
+ s = convert_rows_boolean_to_fixnum(solve_exact_cover( @b1))
185
+ assert_equal(@s1.sort, s.sort)
186
+
187
+ s = solve_exact_cover( convert_rows_fixnum_to_boolean(@a2))
188
+ assert_equal(0, s)
189
+
190
+ s = convert_rows_boolean_to_fixnum(solve_exact_cover( convert_rows_fixnum_to_boolean(@a2), convert_rows_fixnum_to_boolean(@e2)))
191
+ assert_equal(@s2.sort, s.sort)
192
+
193
+ s = convert_rows_boolean_to_fixnum(solve_exact_cover( convert_rows_fixnum_to_boolean(@a3)))
194
+ assert_equal(@s3.sort, s.sort)
195
+
196
+ s = convert_rows_boolean_to_fixnum(solve_exact_cover( convert_rows_fixnum_to_boolean(@a4)))
197
+ assert_equal(@s4.sort, s.sort)
198
+
199
+ s = convert_rows_boolean_to_fixnum(solve_exact_cover( convert_rows_fixnum_to_boolean(@a5)))
200
+ assert_equal(@s5.sort, s.sort)
201
+
202
+ s = solve_exact_cover( convert_rows_fixnum_to_boolean(@a6)){false}
203
+ assert_equal(2, s)
204
+
205
+ end
206
+
207
+ def test_solve_exact_cover2
208
+
209
+ @a7.combinations do |comb|
210
+ s = @s7.clone
211
+ solve_exact_cover(convert_rows_fixnum_to_boolean(comb)) do |result|
212
+ result = convert_rows_boolean_to_fixnum( result ).sort!
213
+ assert( s.member?( result ), "\ncomb: #{comb.to_s}\nresult: #{result}\nsolutions left: #{s.to_s}")
214
+ s.delete result
215
+ false
216
+ end
217
+ assert_equal( [], s)
218
+ end
219
+
220
+ end
221
+
222
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dancing-links
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.1
4
+ version: 0.1.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,9 +11,9 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2012-11-27 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: An implementation of the "dancing links" algorithm to solve the "exact
15
- cover" problem.
16
- email: justin dot w dot smith @t gmail.com
14
+ description: ! " Dancing-links is an implementation of the \"Dancing Links\" algorthm
15
+ to solve the\n \"Exact Cover\" problem. Algorithm found by Donald Knuth.\n"
16
+ email: justin dot w dot smith at gmail dot com
17
17
  executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
@@ -21,7 +21,8 @@ files:
21
21
  - lib/dancing_links.rb
22
22
  - Rakefile
23
23
  - README.rdoc
24
- homepage: https://rubygems.org/gems/dancing-links
24
+ - test/tc_dancing_links.rb
25
+ homepage: http://rubyforge.org/projects/sudoku-gtk/
25
26
  licenses: []
26
27
  post_install_message:
27
28
  rdoc_options: []
@@ -39,10 +40,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
39
40
  - - ! '>='
40
41
  - !ruby/object:Gem::Version
41
42
  version: '0'
42
- requirements: []
43
- rubyforge_project: sudoku-gtk
43
+ requirements:
44
+ - none
45
+ rubyforge_project:
44
46
  rubygems_version: 1.8.11
45
47
  signing_key:
46
48
  specification_version: 3
47
- summary: An implementation of "Dancing Links".
48
- test_files: []
49
+ summary: Implementation of the "Dancing Links" algorithm.
50
+ test_files:
51
+ - test/tc_dancing_links.rb