sudokuhandler 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +104 -113
- data/Rakefile +34 -14
- data/ext/sudoku.c +85 -9
- data/lib/sudoku.rb +33 -197
- data/lib/sudoku/generator.rb +40 -0
- data/lib/sudoku/grid.rb +14 -0
- data/lib/sudoku/logic.rb +242 -0
- data/lib/sudoku/solver.rb +176 -0
- data/lib/sudoku/version.rb +1 -1
- data/tests/test_sudoku.rb +144 -41
- metadata +35 -5
data/README.md
CHANGED
@@ -7,143 +7,134 @@ Le Sudoku "classique" (9x9) est optimisé au maximum en temps et en mémoire (41
|
|
7
7
|
|
8
8
|
### Création d'un sudoku de 9x9 en diagonale
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
$ irb -r sudoku
|
11
|
+
ruby-1.9.2-p290 :000 > s = Sudoku.new 3
|
12
|
+
=> #<Sudoku::S3 9x9 0,0, ... , 0, 0>
|
13
|
+
ruby-1.9.2-p290 :001 > s = Sudoku[3].new
|
14
|
+
=> #<Sudoku::S3 9x9 0,0, ... , 0, 0>
|
15
|
+
ruby-1.9.2-p290 :002 > s.each{|x,y,v| s.set x, x, x+1 if x == y}
|
16
|
+
=> #<Sudoku::S3 9x9 1,0, ... , 0, 9>
|
17
|
+
ruby-1.9.2-p290 :003 > puts s
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
19
|
+
1 . . . . . . . .
|
20
|
+
. 2 . . . . . . .
|
21
|
+
. . 3 . . . . . .
|
22
|
+
|
23
|
+
. . . 4 . . . . .
|
24
|
+
. . . . 5 . . . .
|
25
|
+
. . . . . 6 . . .
|
26
|
+
|
27
|
+
. . . . . . 7 . .
|
28
|
+
. . . . . . . 8 .
|
29
|
+
. . . . . . . . 9
|
30
|
+
=> nil
|
31
31
|
|
32
32
|
###Exportation du sudoku
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
ruby-1.9.2-p290 :004 > s.to_sutxt
|
35
|
+
=> "3: 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 9;"
|
36
|
+
ruby-1.9.2-p290 :005 > s2 = Sudoku.parse s.to_sutxt
|
37
|
+
=> #<Sudoku::S3 9x9 1,0, ... , 0, 9>
|
38
38
|
|
39
39
|
### Un peu de logique
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
41
|
+
ruby-1.9.2-p290 :006 > s.possibilities 0, 1
|
42
|
+
=> [4, 5, 6, 7, 8, 9]
|
43
|
+
ruby-1.9.2-p290 :007 > s.valid? 1, 0, 3
|
44
|
+
=> false
|
45
|
+
ruby-1.9.2-p290 :008 > s.valid? 1, 0, 5
|
46
|
+
=> true
|
47
|
+
ruby-1.9.2-p290 :009 > s.col 2
|
48
|
+
=> [3]
|
49
|
+
ruby-1.9.2-p290 :010 > s.row 3
|
50
|
+
=> [4]
|
51
|
+
ruby-1.9.2-p290 :011 > s.square 3,3
|
52
|
+
=> [4, 5, 6]
|
53
53
|
|
54
54
|
### Generateur
|
55
55
|
|
56
|
-
|
57
|
-
include Sudoku::Generator
|
58
|
-
end
|
59
|
-
|
60
|
-
s = MySudoku.new 5
|
61
|
-
s.make_valid
|
62
|
-
puts s
|
63
|
-
|
64
|
-
=begin =>>
|
65
|
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
66
|
-
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5
|
67
|
-
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10
|
68
|
-
16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
69
|
-
21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
70
|
-
|
71
|
-
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1
|
72
|
-
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6
|
73
|
-
12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11
|
74
|
-
17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
75
|
-
22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
56
|
+
Sudoku.new(5).make_valid
|
76
57
|
|
77
|
-
|
78
|
-
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7
|
79
|
-
13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12
|
80
|
-
18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
81
|
-
23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
58
|
+
donne (par exemple)
|
82
59
|
|
83
|
-
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3
|
84
|
-
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8
|
85
|
-
14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13
|
86
|
-
19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
87
|
-
24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
88
|
-
|
89
|
-
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4
|
90
|
-
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9
|
91
|
-
15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
92
|
-
20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
93
|
-
25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
94
|
-
=end
|
95
60
|
|
96
|
-
|
97
|
-
|
98
|
-
|
61
|
+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
62
|
+
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5
|
63
|
+
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10
|
64
|
+
16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
65
|
+
21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
66
|
+
|
67
|
+
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1
|
68
|
+
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6
|
69
|
+
12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11
|
70
|
+
17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
71
|
+
22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
72
|
+
|
73
|
+
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2
|
74
|
+
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7
|
75
|
+
13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12
|
76
|
+
18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
77
|
+
23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
78
|
+
|
79
|
+
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3
|
80
|
+
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8
|
81
|
+
14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13
|
82
|
+
19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
83
|
+
24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
84
|
+
|
85
|
+
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4
|
86
|
+
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9
|
87
|
+
15 16 17 18 19 20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
88
|
+
20 21 22 23 24 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
89
|
+
25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
99
90
|
|
100
91
|
### Utiliser son propre adapteur
|
101
92
|
|
102
|
-
####
|
93
|
+
#### Interface minimale d'un adapteur
|
103
94
|
|
104
|
-
* get(x, y)
|
105
|
-
* set(x, y, val)
|
106
|
-
* each(){|x, y, val| ... }
|
107
|
-
* size()
|
108
|
-
* initialize(base)
|
95
|
+
* get(x, y) => Fixnum
|
96
|
+
* set(x, y, val) => Fixnum
|
97
|
+
* each(){|x, y, val| ... } => self
|
98
|
+
* size() => Fixnum
|
99
|
+
* initialize(base) => self
|
109
100
|
* initialize_copy(parent) (automatique si on n'utilise que des objets ruby)
|
110
101
|
|
111
102
|
#### Exemple:
|
112
103
|
|
113
104
|
NB: cet exemple ne tient pas compte de la gestion des erreurs
|
114
105
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
def each
|
135
|
-
@data.each_with_index do |val, i|
|
136
|
-
yield i%size, i/size, val
|
137
|
-
end
|
138
|
-
self
|
139
|
-
end
|
106
|
+
class MonSuperAdapteur
|
107
|
+
attr_reader :size
|
108
|
+
|
109
|
+
include Sudoku::Generator #methodes de generation automatique
|
110
|
+
include Sudoku::Grid #methodes communes a tous les sudokus
|
111
|
+
|
112
|
+
def initialize base
|
113
|
+
@size = base*base
|
114
|
+
@data = Array.new(@size*@size){0}
|
115
|
+
end
|
116
|
+
|
117
|
+
def get x, y
|
118
|
+
@data[x+y*size]
|
119
|
+
end
|
120
|
+
|
121
|
+
def set x, y, val
|
122
|
+
@data[x+y*size] = val
|
140
123
|
end
|
141
124
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
125
|
+
def each
|
126
|
+
@data.each_with_index do |val, i|
|
127
|
+
yield i%size, i/size, val
|
128
|
+
end
|
129
|
+
self
|
130
|
+
end
|
131
|
+
end
|
146
132
|
|
147
|
-
|
133
|
+
Sudoku[4..7] = MonSuperAdapteur #Tous les sudokus de base 4 à 7 créés automatiquement
|
134
|
+
#seront des MonSuperAdapteur
|
135
|
+
Sudoku.new(3).class # => Sudoku::S3
|
136
|
+
Sudoku.new(4).class # => MonSuperAdapteur
|
137
|
+
|
138
|
+
Sudoku[0] = MonSuperAdapteur #Tous les sudokus, par defaut
|
148
139
|
|
149
|
-
|
140
|
+
Sudoku.new(3).class # => MonSuperAdapteur
|
data/Rakefile
CHANGED
@@ -1,22 +1,30 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake/gempackagetask'
|
3
|
-
|
3
|
+
begin
|
4
|
+
require 'rake/extensiontask'
|
5
|
+
rescue LoadError => e
|
6
|
+
sh "gem install rake-compiler"
|
7
|
+
exec %{rake "#{ARGV*'" "'}"}
|
8
|
+
end
|
4
9
|
require 'rake/testtask.rb'
|
5
10
|
require './lib/sudoku/version'
|
6
11
|
|
7
12
|
spec = Gem::Specification.new do |s|
|
8
|
-
s.name
|
9
|
-
s.version
|
10
|
-
s.platform
|
11
|
-
s.summary
|
12
|
-
s.description
|
13
|
-
s.author
|
14
|
-
s.email
|
15
|
-
s.files
|
16
|
-
s.homepage
|
17
|
-
s.extensions
|
18
|
-
s.license
|
19
|
-
s.test_files
|
13
|
+
s.name = 'sudokuhandler'
|
14
|
+
s.version = Sudoku::VERSION
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.summary = "Ruby Sudoku handler"
|
17
|
+
s.description = "Highly optimised Sudoku objects and mixins for Ruby"
|
18
|
+
s.author = "Titouan Christophe"
|
19
|
+
s.email = 'titouanchristophe@gmail.com'
|
20
|
+
s.files = FileList["lib/*.rb", "lib/sudoku/*.rb", "ext/sudoku.c", "Rakefile", "README.md"]
|
21
|
+
s.homepage = 'http://github.com/titouanc/rb-sudoku'
|
22
|
+
s.extensions << 'ext/extconf.rb'
|
23
|
+
s.license = 'Creative Commons BY-NC-SA 3.0'
|
24
|
+
s.test_files = FileList["tests/*"]
|
25
|
+
s.rdoc_options += ['--title', 'Sudoku for Ruby', '--main', 'README']
|
26
|
+
s.add_development_dependency 'rake-compiler'
|
27
|
+
s.add_development_dependency 'yard'
|
20
28
|
end
|
21
29
|
|
22
30
|
Rake::GemPackageTask.new(spec) do |pkg|
|
@@ -34,6 +42,16 @@ Rake::TestTask.new do |t|
|
|
34
42
|
t.verbose = true
|
35
43
|
end
|
36
44
|
|
45
|
+
begin
|
46
|
+
require 'yard'
|
47
|
+
YARD::Rake::YardocTask.new do |t|
|
48
|
+
t.files = FileList["lib/sudoku.rb", "lib/sudoku/*.rb"]
|
49
|
+
t.options = ['--readme', 'README.md', '--charset', 'UTF-8']
|
50
|
+
end
|
51
|
+
rescue LoadError => e
|
52
|
+
puts "No doc task (YARD required)"
|
53
|
+
end
|
54
|
+
|
37
55
|
desc "Build gem & install"
|
38
56
|
task :install => FileList["pkg/#{spec.full_name}.gem"] do |t|
|
39
57
|
sh "gem install #{t.prerequisites.first}"
|
@@ -54,4 +72,6 @@ task :console => :compile do |t|
|
|
54
72
|
sh "irb -I ./lib -r sudoku"
|
55
73
|
end
|
56
74
|
|
57
|
-
task :
|
75
|
+
task :doc => :yard
|
76
|
+
|
77
|
+
task :default => [:clobber, :repackage, :compile, :test, :yard]
|
data/ext/sudoku.c
CHANGED
@@ -74,13 +74,17 @@ static VALUE S4_15_initCopy(VALUE copy, VALUE orig){
|
|
74
74
|
S4_15 *this, *parent;
|
75
75
|
int len;
|
76
76
|
|
77
|
+
if (copy == orig)
|
78
|
+
return copy;
|
79
|
+
|
77
80
|
Data_Get_Struct(copy, S4_15, this);
|
78
81
|
Data_Get_Struct(orig, S4_15, parent);
|
79
82
|
|
80
83
|
this->size = parent->size;
|
84
|
+
len = this->size * this->size;
|
81
85
|
|
82
86
|
S4_15_alloc_data(this);
|
83
|
-
memcpy(this->ptr, parent->ptr,
|
87
|
+
memcpy(this->ptr, parent->ptr, len*sizeof(char));
|
84
88
|
|
85
89
|
return copy;
|
86
90
|
}
|
@@ -94,7 +98,7 @@ static VALUE S4_15_get(VALUE self, VALUE col, VALUE row){
|
|
94
98
|
if (x<0 || x>=this->size || y<0 || y>=this->size)
|
95
99
|
rb_raise(rb_eArgError, "Are you sure thre's a %d,%d cell in a %dx%d Sudoku ?", x, y, this->size, this->size);
|
96
100
|
|
97
|
-
return
|
101
|
+
return INT2FIX(this->ptr[x+y*this->size]);
|
98
102
|
}
|
99
103
|
|
100
104
|
static VALUE S4_15_set(VALUE self, VALUE col, VALUE row, VALUE value){
|
@@ -150,6 +154,9 @@ static void Init_S4_15(VALUE module){
|
|
150
154
|
|
151
155
|
/* ############################################ */
|
152
156
|
|
157
|
+
#define S3_offset(x, y) ((size_t) (x)+((y)*9))
|
158
|
+
#define S3_valAtOffset(ptr, i) (((i)%2 == 0) ? (((ptr)[(i)/2] >> 4) & 0x0f) : ((ptr)[(i)/2] & 0x0f))
|
159
|
+
|
153
160
|
static void S3_dealloc(void *ptr){
|
154
161
|
free(ptr);
|
155
162
|
}
|
@@ -179,6 +186,9 @@ static VALUE S3_initCopy(VALUE copy, VALUE orig){
|
|
179
186
|
unsigned char *this, *parent;
|
180
187
|
char i;
|
181
188
|
|
189
|
+
if (copy == orig)
|
190
|
+
return copy;
|
191
|
+
|
182
192
|
Data_Get_Struct(copy, unsigned char, this);
|
183
193
|
Data_Get_Struct(orig, unsigned char, parent);
|
184
194
|
if (this == parent)
|
@@ -190,7 +200,7 @@ static VALUE S3_initCopy(VALUE copy, VALUE orig){
|
|
190
200
|
}
|
191
201
|
|
192
202
|
static VALUE S3_get(VALUE self, VALUE col, VALUE row){
|
193
|
-
unsigned char *this, x, y
|
203
|
+
unsigned char *this, x, y;
|
194
204
|
|
195
205
|
Data_Get_Struct(self, unsigned char, this);
|
196
206
|
x = NUM2UINT(col)&0xff;
|
@@ -199,11 +209,7 @@ static VALUE S3_get(VALUE self, VALUE col, VALUE row){
|
|
199
209
|
if (x>=9 || y>=9)
|
200
210
|
rb_raise(rb_eArgError, "Are you sure thre's a %d,%d cell in a 9x9 Sudoku ?", x, y);
|
201
211
|
|
202
|
-
|
203
|
-
if (i%2 == 0)
|
204
|
-
return INT2FIX((this[i/2] >> 4) & 0x0f);
|
205
|
-
else
|
206
|
-
return INT2FIX(this[i/2] & 0x0f);
|
212
|
+
return INT2FIX(S3_valAtOffset(this, S3_offset(x, y)));
|
207
213
|
}
|
208
214
|
|
209
215
|
static VALUE S3_set(VALUE self, VALUE col, VALUE row, VALUE value){
|
@@ -218,7 +224,7 @@ static VALUE S3_set(VALUE self, VALUE col, VALUE row, VALUE value){
|
|
218
224
|
if (x>=9 || y>=9 || val > 9)
|
219
225
|
rb_raise(rb_eArgError, "%d,%d => %d not allowed in a 9x9 Sudoku", x, y, val);
|
220
226
|
|
221
|
-
i = x
|
227
|
+
i = S3_offset(x, y);
|
222
228
|
if (i%2 == 0)
|
223
229
|
this[i/2] = (this[i/2]&0x0f) | (val<<4);
|
224
230
|
else
|
@@ -248,6 +254,48 @@ static VALUE S3_each(VALUE self){
|
|
248
254
|
return self;
|
249
255
|
}
|
250
256
|
|
257
|
+
static VALUE S3_column(VALUE self, VALUE col){
|
258
|
+
unsigned char x = NUM2UINT(col)&0xff, y, val;
|
259
|
+
unsigned char i = x;
|
260
|
+
VALUE res;
|
261
|
+
unsigned char *this;
|
262
|
+
|
263
|
+
if (x>=9)
|
264
|
+
rb_raise(rb_eArgError, "Are you sure thre's a %d column in a 9x9 Sudoku ?", x);
|
265
|
+
|
266
|
+
Data_Get_Struct(self, unsigned char, this);
|
267
|
+
res = rb_ary_new();
|
268
|
+
for (y=0; y<9; y++){
|
269
|
+
val = S3_valAtOffset(this, i);
|
270
|
+
if (val != 0)
|
271
|
+
rb_ary_push(res, INT2FIX(val));
|
272
|
+
i += 9;
|
273
|
+
}
|
274
|
+
|
275
|
+
return res;
|
276
|
+
}
|
277
|
+
|
278
|
+
static VALUE S3_line(VALUE self, VALUE row){
|
279
|
+
unsigned char y = NUM2UINT(row)&0xff, x, val;
|
280
|
+
unsigned char i = 9*y;
|
281
|
+
VALUE res;
|
282
|
+
unsigned char *this;
|
283
|
+
|
284
|
+
if (y>=9)
|
285
|
+
rb_raise(rb_eArgError, "Are you sure thre's a %d row in a 9x9 Sudoku ?", y);
|
286
|
+
|
287
|
+
Data_Get_Struct(self, unsigned char, this);
|
288
|
+
res = rb_ary_new();
|
289
|
+
for (x=0; x<9; x++){
|
290
|
+
val = S3_valAtOffset(this, i);
|
291
|
+
if (val != 0)
|
292
|
+
rb_ary_push(res, INT2FIX(val));
|
293
|
+
i ++;
|
294
|
+
}
|
295
|
+
|
296
|
+
return res;
|
297
|
+
}
|
298
|
+
|
251
299
|
static VALUE S3_isComplete(VALUE self){
|
252
300
|
char i, val;
|
253
301
|
unsigned char *this;
|
@@ -260,6 +308,31 @@ static VALUE S3_isComplete(VALUE self){
|
|
260
308
|
return Qtrue;
|
261
309
|
}
|
262
310
|
|
311
|
+
static VALUE S3_isValidCell(VALUE self, VALUE col, VALUE row, VALUE val){
|
312
|
+
unsigned char x = NUM2UINT(col)&0xff, xx;
|
313
|
+
unsigned char y = NUM2UINT(row)&0xff, yy;
|
314
|
+
unsigned char v = NUM2UINT(val)&0xff;
|
315
|
+
unsigned char i;
|
316
|
+
unsigned char *this;
|
317
|
+
|
318
|
+
if (x>=9 || y>=9 || v>9)
|
319
|
+
rb_raise(rb_eArgError, "%d,%d => %d not allowed in a 9x9 Sudoku", x, y, v);
|
320
|
+
|
321
|
+
if (v==0)
|
322
|
+
return Qtrue;
|
323
|
+
|
324
|
+
Data_Get_Struct(self, unsigned char, this);
|
325
|
+
for (i=0; i<9; i++){
|
326
|
+
if (S3_valAtOffset(this, S3_offset(x, i)) == v && i != y) return Qfalse;
|
327
|
+
if (S3_valAtOffset(this, S3_offset(i, y)) == v && i != x) return Qfalse;
|
328
|
+
xx = 3*(x/3) + (i%3);
|
329
|
+
yy = 3*(y/3) + (i/3);
|
330
|
+
if (S3_valAtOffset(this, S3_offset(xx, yy))==v && xx!=x && yy!=y) return Qfalse;
|
331
|
+
}
|
332
|
+
|
333
|
+
return Qtrue;
|
334
|
+
}
|
335
|
+
|
263
336
|
static VALUE S3_dump(VALUE self){
|
264
337
|
char string[83] = {'\0'};
|
265
338
|
int i;
|
@@ -283,8 +356,11 @@ static void Init_S3(VALUE module){
|
|
283
356
|
rb_define_method(class_S3, "get", S3_get, 2);
|
284
357
|
rb_define_method(class_S3, "set", S3_set, 3);
|
285
358
|
rb_define_method(class_S3, "each", S3_each, 0);
|
359
|
+
rb_define_method(class_S3, "col", S3_column, 1);
|
360
|
+
rb_define_method(class_S3, "row", S3_line, 1);
|
286
361
|
rb_define_method(class_S3, "complete?", S3_isComplete, 0);
|
287
362
|
rb_define_method(class_S3, "dump", S3_dump, 0);
|
363
|
+
rb_define_method(class_S3, "valid_cell?", S3_isValidCell, 3);
|
288
364
|
}
|
289
365
|
|
290
366
|
/* ############################################ */
|