nsudoku 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +26 -7
- data/lib/nsudoku/checker.rb +0 -1
- data/lib/nsudoku/solver.rb +168 -0
- data/lib/nsudoku/version.rb +1 -1
- data/lib/nsudoku.rb +4 -179
- data/nsudoku.gemspec +2 -2
- data/spec/nsudoku_spec.rb +5 -130
- data/spec/solver_spec.rb +102 -0
- metadata +7 -6
- data/lib/nsudoku/logic.rb +0 -187
- data/spec/logic_spec.rb +0 -85
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Sudoku
|
2
2
|
|
3
|
-
This gem
|
3
|
+
This gem solves puzzle game sudoku (n^2, n^2), for example (3^2, 3^2) = (9, 9) or (4, 4)
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -29,15 +29,34 @@ Usage class NSudoku for example:
|
|
29
29
|
"050906010",
|
30
30
|
"000320908",
|
31
31
|
"000580107",
|
32
|
-
"000000240"
|
32
|
+
"000000240"
|
33
|
+
].join
|
33
34
|
|
34
|
-
Solve
|
35
|
+
Solve the sudoku game
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
Result which match to all solutions of SUDOKU (if sample has got more than one result)
|
38
|
+
|
39
|
+
NSudoku.new(SUDOKU).solve #=> "712460850394852671685170420070208596926715384050906712540320968269584137030690245"
|
40
|
+
|
41
|
+
First correct solution for variable SUDOKU
|
42
|
+
|
43
|
+
NSudoku.new(SUDOKU).solution #=> "712463859394852671685179423173248596926715384458936712541327968269584137837691245"
|
44
|
+
|
45
|
+
You can solve sudoku (4, 4)
|
46
|
+
|
47
|
+
SUDOKU44 = [
|
48
|
+
"1030",
|
49
|
+
"4000",
|
50
|
+
"0140",
|
51
|
+
"3001"
|
52
|
+
].join
|
53
|
+
|
54
|
+
NSudoku.new(SUDOKU44).solution #=> "1234431221433421"
|
55
|
+
NSudoku.new(SUDOKU44).solve #=> "1234431221433421"
|
56
|
+
|
57
|
+
If you see the same results in methods "solution " and "solve", then sudoku has got only one result
|
39
58
|
|
40
59
|
Check whether your array has got that same values in rows, columns or sub blocks. When your array is correct you should expect result nil.
|
41
60
|
In other situation you should received array of position with that same value.
|
42
61
|
|
43
|
-
|
62
|
+
NSudoku::Checker.new(SUDOKU).repeat_in #=> nil
|
data/lib/nsudoku/checker.rb
CHANGED
@@ -0,0 +1,168 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class NSudoku
|
4
|
+
class Solver
|
5
|
+
|
6
|
+
attr_accessor :revers
|
7
|
+
|
8
|
+
def initialize(sudoku)
|
9
|
+
@sudoku = sudoku
|
10
|
+
@width = Math.sqrt(sudoku.length).to_i
|
11
|
+
@block_width = Math.sqrt(@width).to_i
|
12
|
+
@revers = create_revers(@sudoku.split(""))
|
13
|
+
end
|
14
|
+
|
15
|
+
# search result of sudoku
|
16
|
+
def search
|
17
|
+
revers = nil
|
18
|
+
while not revers == @revers
|
19
|
+
revers = Marshal.load(Marshal.dump(@revers))
|
20
|
+
@width.times do |index|
|
21
|
+
[:row, :column, :block].each do |type|
|
22
|
+
search_pair(type, index)
|
23
|
+
search_single(type, index)
|
24
|
+
only_one(type, index)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_revers(data)
|
32
|
+
@revers, index = raw_revers, 0
|
33
|
+
@revers.each_with_index do |row, row_index|
|
34
|
+
row.each_with_index do |col, col_index|
|
35
|
+
cell = data[index]
|
36
|
+
@revers[row_index][col_index] = [cell.to_i] if cell =~ /^[1-9]$/
|
37
|
+
index += 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# revers table @revers into string where cell [n] return n and [a1, a2, ..., ak] return 0
|
43
|
+
def sudoku
|
44
|
+
result = ""
|
45
|
+
@revers.flatten(1).each do |element|
|
46
|
+
result << (element.size == 1 ? element.first.to_s : "0")
|
47
|
+
end
|
48
|
+
result
|
49
|
+
end
|
50
|
+
|
51
|
+
# change positions: external position of block for sudoku and
|
52
|
+
# internal position of block into array [row_position, column_position]
|
53
|
+
def block_position(external, internal)
|
54
|
+
[
|
55
|
+
(external / @block_width) * @block_width + internal / @block_width,
|
56
|
+
(external % @block_width) * @block_width + internal % @block_width
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
# get vector values for row, column or block from variable @revers
|
61
|
+
def get_vector(type, index)
|
62
|
+
result = []
|
63
|
+
case type
|
64
|
+
when :row
|
65
|
+
result = @revers[index]
|
66
|
+
when :column
|
67
|
+
result = @revers.map{ |element| element[index] }
|
68
|
+
when :block
|
69
|
+
@width.times do |block|
|
70
|
+
row, column = block_position(index, block)
|
71
|
+
result << @revers[row][column]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
# get vector values for row, column or block from variable @revers
|
78
|
+
def set_vector(type, index, vector)
|
79
|
+
case type
|
80
|
+
when :row
|
81
|
+
@revers[index] = vector
|
82
|
+
when :column
|
83
|
+
@width.times do |row|
|
84
|
+
@revers[row][index] = vector[row]
|
85
|
+
end
|
86
|
+
when :block
|
87
|
+
@width.times do |block|
|
88
|
+
row, column = block_position(index, block)
|
89
|
+
@revers[row][column] = vector[block]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def positions_values(vector)
|
95
|
+
result = {}
|
96
|
+
vector.each_with_index do |values, index|
|
97
|
+
values.each do |value|
|
98
|
+
(result[value] ||= []) << index
|
99
|
+
end
|
100
|
+
end
|
101
|
+
result
|
102
|
+
end
|
103
|
+
|
104
|
+
def only_two_positions(vector)
|
105
|
+
result = {}
|
106
|
+
positions_values(vector).select do |value, positions|
|
107
|
+
positions.length == 2
|
108
|
+
end.each do |value, positions|
|
109
|
+
(result[positions] ||= []) << value
|
110
|
+
end
|
111
|
+
result
|
112
|
+
end
|
113
|
+
|
114
|
+
# if vector (row, column or block) has got two cells like this [n1, n2, n3] and [n1, n2, n4]
|
115
|
+
# and variables n1, n2 don't exist in other cells of vector than two cells should be equal [n1, n2].
|
116
|
+
# [[1, 4], [2, 4, 1, 3], [1, 2, 4], [4]] #=> [[1, 4], [2, 4], [2, 4], [4]]
|
117
|
+
def search_pair(type, index)
|
118
|
+
vec = get_vector(type, index)
|
119
|
+
only_two_positions(vec).each do |positions, value|
|
120
|
+
next unless value.size == 2
|
121
|
+
vec[positions[0]] = value.clone
|
122
|
+
vec[positions[1]] = value.clone
|
123
|
+
end
|
124
|
+
set_vector(type, index, vec)
|
125
|
+
end
|
126
|
+
|
127
|
+
# if vector (row, column or block) has got cell like this [n1, n2, ..., nk]
|
128
|
+
# and variable ni exist only one in all vector than cell should be equal [ni].
|
129
|
+
# [[1, 2, 3, 4], [2, 4], [1, 2, 4], [1, 4]] #=> [[3], [2, 4], [1, 2, 4], [1, 4]]
|
130
|
+
def only_one(type, index)
|
131
|
+
vec = get_vector(type, index)
|
132
|
+
vec.each_with_index do |values, position|
|
133
|
+
next unless values.size == 1
|
134
|
+
cell = values.first
|
135
|
+
@width.times do |sub_position|
|
136
|
+
vec[sub_position].delete(cell) unless sub_position == position
|
137
|
+
end
|
138
|
+
end
|
139
|
+
set_vector(type, index, vec)
|
140
|
+
end
|
141
|
+
|
142
|
+
# if vector (row, column or block) has got cell like this [n1]
|
143
|
+
# than should be erase value n1 from rest of cells.
|
144
|
+
# [[1, 2, 3, 4], [2], [1, 2, 4], [1, 4]] #=> [[1, 3, 4], [2], [1, 4], [1, 4]]
|
145
|
+
def search_single(type, index)
|
146
|
+
vec = get_vector(type, index)
|
147
|
+
positions_values(vec).each do |value, positions|
|
148
|
+
vec[positions.first] = [value] if positions.size == 1
|
149
|
+
end
|
150
|
+
set_vector(type, index, vec)
|
151
|
+
end
|
152
|
+
|
153
|
+
# @width = 4
|
154
|
+
# cell = [1, 2, 3, 4]
|
155
|
+
# return [[cell, cell, cell, cell],
|
156
|
+
# [cell, cell, cell, cell],
|
157
|
+
# [cell, cell, cell, cell],
|
158
|
+
# [cell, cell, cell, cell]]
|
159
|
+
def raw_revers
|
160
|
+
(1..@width).to_a.map do
|
161
|
+
(1..@width).to_a.map do
|
162
|
+
(1..@width).to_a
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
data/lib/nsudoku/version.rb
CHANGED
data/lib/nsudoku.rb
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require_relative "nsudoku/version"
|
3
3
|
require_relative "nsudoku/checker"
|
4
|
-
require_relative "nsudoku/
|
4
|
+
require_relative "nsudoku/solver"
|
5
5
|
|
6
6
|
class NSudoku
|
7
7
|
|
8
8
|
def initialize(sudoku)
|
9
|
-
@data = sudoku
|
10
9
|
@sudoku = sudoku
|
11
|
-
@revers_table = create_revers_table(sudoku.split(""))
|
12
10
|
@length = @sudoku.length
|
13
11
|
@width = Math.sqrt(@sudoku.length).to_i
|
14
12
|
@block_width = Math.sqrt(@width).to_i
|
@@ -24,27 +22,7 @@ class NSudoku
|
|
24
22
|
|
25
23
|
# return result which match to all solutions of sudoku
|
26
24
|
def solve
|
27
|
-
|
28
|
-
while not revers_table == @revers_table
|
29
|
-
revers_table = Marshal.load(Marshal.dump(@revers_table))
|
30
|
-
|
31
|
-
9.times do |index|
|
32
|
-
cells_with_two_elements_for('row', index)
|
33
|
-
cells_with_two_elements_for('column', index)
|
34
|
-
cells_with_two_elements_for('block', index)
|
35
|
-
erase_in_horizontal_three(index)
|
36
|
-
erase_in_vertical_three(index)
|
37
|
-
end
|
38
|
-
|
39
|
-
9.times do |row|
|
40
|
-
9.times do |column|
|
41
|
-
erase_in_vertical_one(row, column)
|
42
|
-
erase_in_horizontal_one(row, column)
|
43
|
-
erase_in_block_one(row, column)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
revers_table_to_result
|
25
|
+
NSudoku::Solver.new(@sudoku).search.sudoku
|
48
26
|
end
|
49
27
|
|
50
28
|
private
|
@@ -57,167 +35,14 @@ private
|
|
57
35
|
data[position] = value.to_s
|
58
36
|
return unless NSudoku::Checker.new(data).correct?
|
59
37
|
@solution = data.clone if position == @length - 1
|
60
|
-
if @
|
38
|
+
if @sudoku[position + 1] == "0"
|
61
39
|
(1..@width).each do |value|
|
62
40
|
solver(data, position + 1, value)
|
63
41
|
data[position + 1] = "0"
|
64
42
|
end
|
65
43
|
else
|
66
|
-
solver(data, position + 1, @
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# table = [[[1, 2, 3, 4, 5], [], ..., []],
|
71
|
-
# [[], ..., []],
|
72
|
-
# ...
|
73
|
-
# [[], ..., []]
|
74
|
-
# ]
|
75
|
-
def create_revers_table(data)
|
76
|
-
result = 9.times.map{|row_element| 9.times.map{|col_element| []}}
|
77
|
-
data.each_with_index do |cell, index|
|
78
|
-
column = index % 9
|
79
|
-
row = (index - column)/9 % 9
|
80
|
-
cell = cell.to_i
|
81
|
-
result[row][column] = [cell]
|
82
|
-
result[row][column] = 9.times.map{|element| element + 1} if cell == 0
|
83
|
-
end
|
84
|
-
return result
|
85
|
-
end
|
86
|
-
|
87
|
-
# revers table @revers_table into string where cell [n] return n and [a1, a2, ..., ak] return 0
|
88
|
-
def revers_table_to_result
|
89
|
-
result = ""
|
90
|
-
@revers_table.flatten(1).each do |element|
|
91
|
-
result << (element.size == 1 ? element.first.to_s : "0")
|
92
|
-
end
|
93
|
-
result
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
def positions_for(type, index0, index1)
|
98
|
-
case type
|
99
|
-
when 'column'
|
100
|
-
return {
|
101
|
-
row: index0,
|
102
|
-
column: index1
|
103
|
-
}
|
104
|
-
when 'row'
|
105
|
-
return {
|
106
|
-
row: index0,
|
107
|
-
column: index1
|
108
|
-
}
|
109
|
-
when 'block'
|
110
|
-
return {
|
111
|
-
row: (index0/3)*3 + index1/3,
|
112
|
-
column: (index0%3)*3 + index1%3
|
113
|
-
}
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def positions_of_values(kind, value)
|
118
|
-
result = {}
|
119
|
-
row, column = nil, nil
|
120
|
-
9.times do |index|
|
121
|
-
case kind
|
122
|
-
when 'column'
|
123
|
-
row = index
|
124
|
-
column = value
|
125
|
-
when 'row'
|
126
|
-
row = value
|
127
|
-
column = index
|
128
|
-
when 'block'
|
129
|
-
row = (value/3)*3 + index/3
|
130
|
-
column = (value%3)*3 + index%3
|
131
|
-
end
|
132
|
-
next if row.nil? or column.nil?
|
133
|
-
@revers_table[row][column].each do |value|
|
134
|
-
result[value] ||= []
|
135
|
-
result[value] << index
|
136
|
-
end
|
137
|
-
end
|
138
|
-
result
|
139
|
-
end
|
140
|
-
|
141
|
-
# erase values in vertical, which are that same like value from positnio row, column
|
142
|
-
# type: "block", "row","column"
|
143
|
-
def cells_with_two_elements_for(type, index)
|
144
|
-
only_two_positions = positions_of_values(type, index).select {|k,v| v.length == 2}
|
145
|
-
result = {}
|
146
|
-
only_two_positions.each do |value, positions|
|
147
|
-
result[positions] ||= []
|
148
|
-
result[positions] << value
|
44
|
+
solver(data, position + 1, @sudoku[position + 1])
|
149
45
|
end
|
150
|
-
result.each do |key, value|
|
151
|
-
if value.size == 2
|
152
|
-
if type == 'block'
|
153
|
-
positions = positions_for('block', index, key[0])
|
154
|
-
@revers_table[positions[:row]][positions[:column]] = value.clone
|
155
|
-
positions = positions_for('block', index, key[1])
|
156
|
-
@revers_table[positions[:row]][positions[:column]] = value.clone
|
157
|
-
end
|
158
|
-
if type == 'row'
|
159
|
-
@revers_table[index][key[0]] = value.clone
|
160
|
-
@revers_table[index][key[1]] = value.clone
|
161
|
-
end
|
162
|
-
if type == 'column'
|
163
|
-
@revers_table[key[0]][index] = value.clone
|
164
|
-
@revers_table[key[1]][index] = value.clone
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
|
171
|
-
# erase values in vertical, which are that same like value from positnio row, column
|
172
|
-
def erase_in_vertical_one(row, column)
|
173
|
-
return unless @revers_table[row][column].size == 1
|
174
|
-
cell = @revers_table[row][column][0]
|
175
|
-
9.times do |index|
|
176
|
-
@revers_table[index][column].delete(cell) unless index == row
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# erase values in hozizontal, which are that same like value from positnio row, column
|
181
|
-
def erase_in_horizontal_one(row, column)
|
182
|
-
return unless @revers_table[row][column].size == 1
|
183
|
-
cell = @revers_table[row][column][0]
|
184
|
-
9.times do |index|
|
185
|
-
@revers_table[row][index].delete(cell) unless index == column
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
# erase values in block, which are that same like value from positnio row, column
|
190
|
-
def erase_in_block_one(row, column)
|
191
|
-
return unless @revers_table[row][column].size == 1
|
192
|
-
cell = @revers_table[row][column][0]
|
193
|
-
first_row_block = (row/3)*3
|
194
|
-
first_column_block = (column/3)*3
|
195
|
-
3.times do |row_index|
|
196
|
-
row_block = first_row_block + row_index
|
197
|
-
3.times do |column_index|
|
198
|
-
column_block = first_column_block + column_index
|
199
|
-
@revers_table[row_block][column_block].delete(cell) unless row_block == row and column_block == column
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
# erase values in vertical, which are that same like value from positnio row, column
|
205
|
-
def erase_in_vertical_three(column)
|
206
|
-
positions_of_values('column', column).each do |value, positions|
|
207
|
-
@revers_table[positions.first][column] = [value] if positions.size == 1
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
# erase values in horizontal, which are that same like value from positnio row, column
|
212
|
-
def erase_in_horizontal_three(row)
|
213
|
-
positions_of_values('row', row).each do |value, positions|
|
214
|
-
@revers_table[row][positions.first] = [value] if positions.size == 1
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
def cell_revers_table(row, column, value = nil)
|
219
|
-
@revers_table[row][column] = value unless value.nil?
|
220
|
-
@revers_table[row][column]
|
221
46
|
end
|
222
47
|
|
223
48
|
end
|
data/nsudoku.gemspec
CHANGED
@@ -5,8 +5,8 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.platform = Gem::Platform::RUBY
|
6
6
|
gem.authors = ["Michał Szyma"]
|
7
7
|
gem.email = ["raglub.ruby@gmail.com"]
|
8
|
-
gem.date = "2012-11-
|
9
|
-
gem.description = %q{This gem solve puzzle game sudoku
|
8
|
+
gem.date = "2012-11-16"
|
9
|
+
gem.description = %q{This gem solve puzzle game sudoku (n^2, n^2), for example (3^2, 3^2) = (9, 9)}
|
10
10
|
gem.summary = %q{This gem solve puzzle game sudoku}
|
11
11
|
gem.homepage = "http://github.com/raglub/nsudoku"
|
12
12
|
|
data/spec/nsudoku_spec.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'nsudoku'
|
4
4
|
|
5
|
-
|
5
|
+
SUDOKU99 = [
|
6
6
|
"012000000",
|
7
7
|
"304052000",
|
8
8
|
"605170000",
|
@@ -13,17 +13,6 @@ EXAMPLE = [
|
|
13
13
|
"000580107",
|
14
14
|
"000000240"].join
|
15
15
|
|
16
|
-
TABLE_EMPTY = [
|
17
|
-
"000000000",
|
18
|
-
"000000000",
|
19
|
-
"000000000",
|
20
|
-
"000000000",
|
21
|
-
"000000000",
|
22
|
-
"000000000",
|
23
|
-
"000000000",
|
24
|
-
"000000000",
|
25
|
-
"000000000"].join
|
26
|
-
|
27
16
|
SUDOKU44 = [
|
28
17
|
"1030",
|
29
18
|
"4000",
|
@@ -34,125 +23,11 @@ describe NSudoku do
|
|
34
23
|
|
35
24
|
it "should properly resolved game sudoku" do
|
36
25
|
NSudoku.new(SUDOKU44).solution.should eq("1234431221433421")
|
26
|
+
NSudoku.new(SUDOKU99).solution.should eq("712463859394852671685179423173248596926715384458936712541327968269584137837691245")
|
37
27
|
end
|
38
28
|
|
39
|
-
it "should
|
40
|
-
|
41
|
-
|
42
|
-
sudoku.send(:cell_revers_table, 8, 8, [3])
|
43
|
-
sudoku.send(:cell_revers_table, 1, 1).should eql([1])
|
44
|
-
sudoku.send(:cell_revers_table, 1 ,0).should eql([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
45
|
-
end
|
46
|
-
|
47
|
-
context "should properly erase values which are that same like in cell with single element" do
|
48
|
-
it "in column (exist cell with single element)" do
|
49
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
50
|
-
sudoku.send(:cell_revers_table, 3, 4, [5])
|
51
|
-
sudoku.send(:erase_in_vertical_one, 3, 4)
|
52
|
-
sudoku.send(:cell_revers_table, 0, 4).should eql([1, 2, 3, 4, 6, 7, 8, 9])
|
53
|
-
sudoku.send(:cell_revers_table, 5, 4).should eql([1, 2, 3, 4, 6, 7, 8, 9])
|
54
|
-
sudoku.send(:cell_revers_table, 8, 4).should eql([1, 2, 3, 4, 6, 7, 8, 9])
|
55
|
-
sudoku.send(:cell_revers_table, 3, 4).should eql([5])
|
56
|
-
end
|
57
|
-
|
58
|
-
it "in column (don't exist cell with single element)" do
|
59
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
60
|
-
sudoku.send(:erase_in_vertical_one, 3, 4)
|
61
|
-
sudoku.send(:cell_revers_table, 5, 4).should eql([1, 2, 3, 4,5 , 6, 7, 8, 9])
|
62
|
-
sudoku.send(:cell_revers_table, 3, 4).should eql([1, 2, 3, 4,5 , 6, 7, 8, 9])
|
63
|
-
end
|
64
|
-
|
65
|
-
it "in row (exist cell with single element)" do
|
66
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
67
|
-
sudoku.send(:cell_revers_table, 3, 4, [5])
|
68
|
-
sudoku.send(:erase_in_horizontal_one, 3, 4)
|
69
|
-
sudoku.send(:cell_revers_table, 3, 2).should eql([1, 2, 3, 4, 6, 7, 8, 9])
|
70
|
-
sudoku.send(:cell_revers_table, 3, 4).should eql([5])
|
71
|
-
end
|
72
|
-
|
73
|
-
it "in column (don't exist cell with single element)" do
|
74
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
75
|
-
sudoku.send(:erase_in_horizontal_one, 3, 4)
|
76
|
-
sudoku.send(:cell_revers_table, 3, 2).should eql([1, 2, 3, 4, 5, 6, 7, 8, 9])
|
77
|
-
sudoku.send(:cell_revers_table, 3, 4).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
78
|
-
end
|
79
|
-
|
80
|
-
it "in block (exist cell with single element)" do
|
81
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
82
|
-
sudoku.send(:cell_revers_table, 7, 3, [8])
|
83
|
-
sudoku.send(:erase_in_block_one, 7, 3)
|
84
|
-
sudoku.send(:cell_revers_table, 6, 2).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
85
|
-
sudoku.send(:cell_revers_table, 5, 6).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
86
|
-
sudoku.send(:cell_revers_table, 5, 3).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
87
|
-
sudoku.send(:cell_revers_table, 7, 6).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
88
|
-
|
89
|
-
sudoku.send(:cell_revers_table, 6, 4).should eql([1, 2, 3, 4 ,5, 6, 7, 9])
|
90
|
-
sudoku.send(:cell_revers_table, 8, 3).should eql([1, 2, 3, 4 ,5, 6, 7, 9])
|
91
|
-
sudoku.send(:cell_revers_table, 8, 5).should eql([1, 2, 3, 4 ,5, 6, 7, 9])
|
92
|
-
sudoku.send(:cell_revers_table, 7, 3).should eql([8])
|
93
|
-
end
|
94
|
-
|
95
|
-
it "in block (don't exist cell with single element)" do
|
96
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
97
|
-
sudoku.send(:erase_in_block_one, 7, 3)
|
98
|
-
sudoku.send(:cell_revers_table, 6, 2).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
99
|
-
sudoku.send(:cell_revers_table, 5, 6).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
100
|
-
|
101
|
-
sudoku.send(:cell_revers_table, 6, 4).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
102
|
-
sudoku.send(:cell_revers_table, 8, 3).should eql([1, 2, 3, 4 ,5, 6, 7, 8, 9])
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context "select cells with two elements (rest erase)" do
|
107
|
-
|
108
|
-
it "in block" do
|
109
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
110
|
-
3.times do |row|
|
111
|
-
3.times do |column|
|
112
|
-
sudoku.send(:cell_revers_table, row, column, [2, 3, 4, 5, 6, 7, 9])
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
sudoku.send(:cell_revers_table, 0, 0, [1, 5, 8])
|
117
|
-
sudoku.send(:cell_revers_table, 2, 2, [1, 3, 8])
|
118
|
-
|
119
|
-
sudoku.send(:cells_with_two_elements_for, "block", 0)
|
120
|
-
sudoku.send(:cell_revers_table, 0, 0).should eql([1, 8])
|
121
|
-
sudoku.send(:cell_revers_table, 2, 2).should eql([1, 8])
|
122
|
-
sudoku.send(:cell_revers_table, 1, 2).should eql([2, 3, 4, 5, 6, 7, 9])
|
123
|
-
end
|
124
|
-
|
125
|
-
it "in column" do
|
126
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
127
|
-
sudoku.send(:cell_revers_table, 0, 4, [1, 5, 8])
|
128
|
-
sudoku.send(:cell_revers_table, 1, 4, [1, 3, 8])
|
129
|
-
(2..8).each do |index|
|
130
|
-
sudoku.send(:cell_revers_table, index, 4, [2, 3, 4, 5, 6, 7, 9])
|
131
|
-
end
|
132
|
-
|
133
|
-
sudoku.send(:cells_with_two_elements_for, "column", 4)
|
134
|
-
sudoku.send(:cell_revers_table, 0, 4).should eql([1, 8])
|
135
|
-
sudoku.send(:cell_revers_table, 1, 4).should eql([1, 8])
|
136
|
-
sudoku.send(:cell_revers_table, 2, 4).should eql([2, 3, 4, 5, 6, 7, 9])
|
137
|
-
end
|
138
|
-
|
139
|
-
it "in row" do
|
140
|
-
sudoku = NSudoku.new(TABLE_EMPTY)
|
141
|
-
sudoku.send(:cell_revers_table, 4, 0, [1, 5, 8])
|
142
|
-
sudoku.send(:cell_revers_table, 4, 1, [1, 3, 8])
|
143
|
-
(2..8).each do |index|
|
144
|
-
sudoku.send(:cell_revers_table, 4, index, [2, 3, 4, 5, 6, 7, 9])
|
145
|
-
end
|
146
|
-
|
147
|
-
sudoku.send(:cells_with_two_elements_for, "row", 4)
|
148
|
-
sudoku.send(:cell_revers_table, 4, 0).should eql([1, 8])
|
149
|
-
sudoku.send(:cell_revers_table, 4, 1).should eql([1, 8])
|
150
|
-
sudoku.send(:cell_revers_table, 4, 2).should eql([2, 3, 4, 5, 6, 7, 9])
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
154
|
-
|
155
|
-
it "solve whole sudoku" do
|
156
|
-
NSudoku.new(EXAMPLE).solve.should eql("712460850394852671685170420070208596926715384050906712540320968269584137030690245")
|
29
|
+
it "should solve game sudoku" do
|
30
|
+
NSudoku.new(SUDOKU44).solve.should eq("1234431221433421")
|
31
|
+
NSudoku.new(SUDOKU99).solve.should eql("712460850394852671685170420070208596926715384050906712540320968269584137030690245")
|
157
32
|
end
|
158
33
|
end
|
data/spec/solver_spec.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'nsudoku'
|
4
|
+
|
5
|
+
EXAMPLE = [
|
6
|
+
"1004",
|
7
|
+
"0302",
|
8
|
+
"0143",
|
9
|
+
"3020"].join
|
10
|
+
|
11
|
+
# REVERS = [
|
12
|
+
# [[1], [1, 2, 3, 4], [1, 2, 3, 4], [4]],
|
13
|
+
# [[1, 2, 3, 4], [2], [1, 2, 3, 4], [1]],
|
14
|
+
# [[1, 2, 3, 4], [1], [4], [3]],
|
15
|
+
# [[2], [1, 2, 3, 4], [1], [1, 2, 3, 4]]
|
16
|
+
# ]
|
17
|
+
|
18
|
+
describe NSudoku do
|
19
|
+
|
20
|
+
before do
|
21
|
+
@logic = NSudoku::Solver.new(EXAMPLE)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can generate reverse of sudoku" do
|
25
|
+
@logic.revers[0][1].should eql([1, 2, 3, 4])
|
26
|
+
@logic.revers[3][3].inspect
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can get result" do
|
30
|
+
@logic.sudoku.should eql(EXAMPLE)
|
31
|
+
end
|
32
|
+
|
33
|
+
context "can erase that same elements in" do
|
34
|
+
it "column" do
|
35
|
+
@logic.set_vector(:column, 3, [[1, 3], [1, 2, 3, 4], [1, 3, 4], [4]])
|
36
|
+
@logic.only_one(:column, 3)
|
37
|
+
@logic.get_vector(:column, 3).should eq([[1, 3], [1, 2, 3], [1, 3], [4]])
|
38
|
+
end
|
39
|
+
|
40
|
+
it "row" do
|
41
|
+
@logic.set_vector(:column, 3, [[1, 3], [1, 2, 3, 4], [1, 3, 4], [4]])
|
42
|
+
@logic.only_one(:column, 3)
|
43
|
+
@logic.get_vector(:column, 3).should eq([[1, 3], [1, 2, 3], [1, 3], [4]])
|
44
|
+
end
|
45
|
+
|
46
|
+
it "block" do
|
47
|
+
@logic.set_vector(:block, 1, [[1, 2, 3], [2], [1, 2, 3, 4], [4]])
|
48
|
+
@logic.only_one(:block, 1)
|
49
|
+
@logic.get_vector(:block, 1).should eq([[1, 3], [2], [1, 3], [4]])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "can choos only one value in elements for" do
|
54
|
+
it "vertical situation" do
|
55
|
+
@logic.set_vector(:column, 2, [[1, 3], [1, 2, 3, 4], [1, 3, 4], [4]])
|
56
|
+
@logic.search_single(:column, 2)
|
57
|
+
@logic.get_vector(:column, 2).should eq([[1, 3], [2], [1, 3, 4], [4]])
|
58
|
+
end
|
59
|
+
|
60
|
+
it "horizontal situation" do
|
61
|
+
@logic.set_vector(:row, 2, [[1, 3], [1, 2, 3, 4], [1, 3, 4], [4]])
|
62
|
+
@logic.search_single(:row, 2)
|
63
|
+
@logic.get_vector(:row, 2).should eq([[1, 3], [2], [1, 3, 4], [4]])
|
64
|
+
end
|
65
|
+
|
66
|
+
it "block situation" do
|
67
|
+
@logic.set_vector(:block, 2, [[1, 3], [1, 2, 3, 4], [1, 3, 4], [4]])
|
68
|
+
@logic.search_single(:block, 2)
|
69
|
+
@logic.get_vector(:block, 2).should eq([[1, 3], [2], [1, 3, 4], [4]])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "can choose only two values in elements for" do
|
74
|
+
it "vertical situation" do
|
75
|
+
@logic.set_vector(:column, 2, [[1], [1, 2, 3, 4], [1, 2, 3, 4], [4]])
|
76
|
+
@logic.search_pair(:column, 2)
|
77
|
+
@logic.get_vector(:column, 2).should eq([[1], [2, 3], [2, 3], [4]])
|
78
|
+
end
|
79
|
+
|
80
|
+
it "horizontal situation" do
|
81
|
+
@logic.set_vector(:row, 3, [[3], [1, 2, 3, 4], [1, 2, 4], [4]])
|
82
|
+
@logic.search_pair(:row, 3)
|
83
|
+
@logic.get_vector(:row, 3).should eq([[3], [1, 2], [1, 2], [4]])
|
84
|
+
end
|
85
|
+
|
86
|
+
it "block situation" do
|
87
|
+
@logic.set_vector(:block, 0, [[1], [1, 2, 3, 4], [1, 2, 3, 4], [4]])
|
88
|
+
@logic.search_pair(:block, 0)
|
89
|
+
@logic.get_vector(:block, 0).should eq([[1], [2, 3], [2, 3], [4]])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "can solve the sudoku" do
|
94
|
+
NSudoku::Solver.new(EXAMPLE).search.sudoku.should eql(
|
95
|
+
"1234" +
|
96
|
+
"4312" +
|
97
|
+
"2143" +
|
98
|
+
"3421"
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nsudoku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -27,7 +27,8 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 2.10.0
|
30
|
-
description: This gem solve puzzle game sudoku
|
30
|
+
description: This gem solve puzzle game sudoku (n^2, n^2), for example (3^2, 3^2)
|
31
|
+
= (9, 9)
|
31
32
|
email:
|
32
33
|
- raglub.ruby@gmail.com
|
33
34
|
executables: []
|
@@ -42,13 +43,13 @@ files:
|
|
42
43
|
- Rakefile
|
43
44
|
- lib/nsudoku.rb
|
44
45
|
- lib/nsudoku/checker.rb
|
45
|
-
- lib/nsudoku/
|
46
|
+
- lib/nsudoku/solver.rb
|
46
47
|
- lib/nsudoku/version.rb
|
47
48
|
- lib/sudoku.rb~
|
48
49
|
- nsudoku.gemspec
|
49
50
|
- spec/checker_spec.rb
|
50
|
-
- spec/logic_spec.rb
|
51
51
|
- spec/nsudoku_spec.rb
|
52
|
+
- spec/solver_spec.rb
|
52
53
|
homepage: http://github.com/raglub/nsudoku
|
53
54
|
licenses: []
|
54
55
|
post_install_message:
|
@@ -75,5 +76,5 @@ specification_version: 3
|
|
75
76
|
summary: This gem solve puzzle game sudoku
|
76
77
|
test_files:
|
77
78
|
- spec/checker_spec.rb
|
78
|
-
- spec/logic_spec.rb
|
79
79
|
- spec/nsudoku_spec.rb
|
80
|
+
- spec/solver_spec.rb
|
data/lib/nsudoku/logic.rb
DELETED
@@ -1,187 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
class NSudoku
|
4
|
-
class Logic
|
5
|
-
|
6
|
-
attr_accessor :revers
|
7
|
-
|
8
|
-
def initialize(sudoku)
|
9
|
-
@sudoku = sudoku
|
10
|
-
@width = Math.sqrt(sudoku.length).to_i
|
11
|
-
@block_width = Math.sqrt(@width).to_i
|
12
|
-
@revers = create_revers(@sudoku.split(""))
|
13
|
-
end
|
14
|
-
|
15
|
-
def create_revers(data)
|
16
|
-
@revers, index = raw_revers, 0
|
17
|
-
@revers.each_with_index do |row, row_index|
|
18
|
-
row.each_with_index do |col, col_index|
|
19
|
-
cell = data[index]
|
20
|
-
@revers[row_index][col_index] = [cell.to_i] if cell =~ /^[1-9]$/
|
21
|
-
index += 1
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
# revers table @revers_table into string where cell [n] return n and [a1, a2, ..., ak] return 0
|
27
|
-
def sudoku
|
28
|
-
result = ""
|
29
|
-
@revers.flatten(1).each do |element|
|
30
|
-
result << (element.size == 1 ? element.first.to_s : "0")
|
31
|
-
end
|
32
|
-
result
|
33
|
-
end
|
34
|
-
|
35
|
-
# change positions: external position of block for sudoku and
|
36
|
-
# internal position of block into array [row_position, column_position]
|
37
|
-
def block_position(external, internal)
|
38
|
-
[
|
39
|
-
(external / @block_width) * @block_width + internal / @block_width,
|
40
|
-
(external % @block_width) * @block_width + internal % @block_width
|
41
|
-
]
|
42
|
-
end
|
43
|
-
|
44
|
-
def block_positions_values(external)
|
45
|
-
result = {}
|
46
|
-
@width.times do |internal|
|
47
|
-
row, column = block_position(external, internal)
|
48
|
-
@revers[row][column].each { |value| (result[value] ||= []) << [row, column] }
|
49
|
-
end
|
50
|
-
result
|
51
|
-
end
|
52
|
-
|
53
|
-
def row_positions_values(row)
|
54
|
-
result = {}
|
55
|
-
@width.times do |column|
|
56
|
-
@revers[row][column].each { |value| (result[value] ||= []) << column }
|
57
|
-
end
|
58
|
-
result
|
59
|
-
end
|
60
|
-
|
61
|
-
def column_positions_values(column)
|
62
|
-
result = {}
|
63
|
-
@width.times do |row|
|
64
|
-
@revers[row][column].each { |value| (result[value] ||= []) << row }
|
65
|
-
end
|
66
|
-
result
|
67
|
-
end
|
68
|
-
|
69
|
-
# erase values in vertical, which are that same like value from positnio row, column
|
70
|
-
def one_element_vertical(column)
|
71
|
-
column_positions_values(column).each do |value, positions|
|
72
|
-
@revers[positions.first][column] = [value] if positions.size == 1
|
73
|
-
end
|
74
|
-
self
|
75
|
-
end
|
76
|
-
|
77
|
-
# erase values in horizontal, which are that same like value from positnio row, column
|
78
|
-
def one_element_horizontal(row)
|
79
|
-
row_positions_values(row).each do |value, positions|
|
80
|
-
@revers[row][positions.first] = [value] if positions.size == 1
|
81
|
-
end
|
82
|
-
self
|
83
|
-
end
|
84
|
-
|
85
|
-
# erase values in block, which are that same like value from positnio row, column
|
86
|
-
def one_element_block(row)
|
87
|
-
block_positions_values(row).each do |value, positions|
|
88
|
-
horizontal = positions[0][0]
|
89
|
-
vertical = positions[0][1]
|
90
|
-
@revers[horizontal][vertical] = [value] if positions.size == 1
|
91
|
-
end
|
92
|
-
self
|
93
|
-
end
|
94
|
-
|
95
|
-
# erase values in block, which are that same like value from positnio row, column
|
96
|
-
def two_elements_block(index)
|
97
|
-
result = {}
|
98
|
-
only_two_positions = block_positions_values(index).select {|k,v| v.length == 2}
|
99
|
-
only_two_positions.each { |value, positions| (result[positions] ||= []) << value }
|
100
|
-
result.each do |positions, value|
|
101
|
-
next unless value.size == 2
|
102
|
-
@revers[positions[0][0]][positions[0][1]] = value.clone
|
103
|
-
@revers[positions[1][0]][positions[1][1]] = value.clone
|
104
|
-
end
|
105
|
-
self
|
106
|
-
end
|
107
|
-
|
108
|
-
# erase values in vertical, which are that same like value from positnio row, column
|
109
|
-
def two_elements_column(column)
|
110
|
-
result = {}
|
111
|
-
only_two_positions = row_positions_values(column).select {|k,v| v.length == 2}
|
112
|
-
only_two_positions.each { |value, positions| (result[positions] ||= []) << value }
|
113
|
-
result.each do |positions, value|
|
114
|
-
next unless value.size == 2
|
115
|
-
@revers[positions[0]][column] = value.clone
|
116
|
-
@revers[positions[1]][column] = value.clone
|
117
|
-
end
|
118
|
-
self
|
119
|
-
end
|
120
|
-
|
121
|
-
# erase values in row, which are that same like value from positnio row, column
|
122
|
-
def two_elements_row(row)
|
123
|
-
result = {}
|
124
|
-
only_two_positions = column_positions_values(row).select {|k,v| v.length == 2}
|
125
|
-
only_two_positions.each { |value, positions| (result[positions] ||= []) << value }
|
126
|
-
result.each do |positions, value|
|
127
|
-
next unless value.size == 2
|
128
|
-
@revers[row][positions[0]] = value.clone
|
129
|
-
@revers[row][positions[1]] = value.clone
|
130
|
-
end
|
131
|
-
self
|
132
|
-
end
|
133
|
-
|
134
|
-
# erase values in vertical, which are that same like value from positnio row, column
|
135
|
-
def erase_elements_row(row, column)
|
136
|
-
return unless @revers[row][column].size == 1
|
137
|
-
cell = @revers[row][column][0]
|
138
|
-
@width.times do |index|
|
139
|
-
@revers[index][column].delete(cell) unless index == row
|
140
|
-
end
|
141
|
-
self
|
142
|
-
end
|
143
|
-
|
144
|
-
# erase values in hozizontal, which are that same like value from positnio row, column
|
145
|
-
def erase_elements_column(row, column)
|
146
|
-
return unless @revers[row][column].size == 1
|
147
|
-
cell = @revers[row][column][0]
|
148
|
-
@width.times do |index|
|
149
|
-
@revers[row][index].delete(cell) unless index == column
|
150
|
-
end
|
151
|
-
self
|
152
|
-
end
|
153
|
-
|
154
|
-
# erase values in block, which are that same like value from positnio row, column
|
155
|
-
def erase_elements_block(row, column)
|
156
|
-
return unless @revers[row][column].size == 1
|
157
|
-
cell = @revers[row][column][0]
|
158
|
-
block_positions(row, column).each do |horizontal, vertical|
|
159
|
-
@revers[horizontal][vertical].delete(cell) unless horizontal == row and vertical == column
|
160
|
-
end
|
161
|
-
self
|
162
|
-
end
|
163
|
-
|
164
|
-
def block_positions(row, column)
|
165
|
-
row_block = (row / @block_width) * @block_width
|
166
|
-
column_block = (column / @block_width) * @block_width
|
167
|
-
(0...@width).to_a.map { |index| [row_block + index / @block_width, column_block + index % @block_width] }
|
168
|
-
end
|
169
|
-
|
170
|
-
private
|
171
|
-
|
172
|
-
# @width = 4
|
173
|
-
# cell = [1, 2, 3, 4]
|
174
|
-
# return [[cell, cell, cell, cell],
|
175
|
-
# [cell, cell, cell, cell],
|
176
|
-
# [cell, cell, cell, cell],
|
177
|
-
# [cell, cell, cell, cell]]
|
178
|
-
def raw_revers
|
179
|
-
(1..@width).to_a.map do
|
180
|
-
(1..@width).to_a.map do
|
181
|
-
(1..@width).to_a
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
end
|
187
|
-
end
|
data/spec/logic_spec.rb
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'nsudoku'
|
4
|
-
|
5
|
-
EXAMPLE = [
|
6
|
-
"1004",
|
7
|
-
"0201",
|
8
|
-
"0143",
|
9
|
-
"2010"].join
|
10
|
-
|
11
|
-
# REVERS = [
|
12
|
-
# [[1], [1, 2, 3, 4], [1, 2, 3, 4], [4]],
|
13
|
-
# [[1, 2, 3, 4], [2], [1, 2, 3, 4], [1]],
|
14
|
-
# [[1, 2, 3, 4], [1], [4], [3]],
|
15
|
-
# [[2], [1, 2, 3, 4], [1], [1, 2, 3, 4]]
|
16
|
-
# ]
|
17
|
-
|
18
|
-
REVERS = [
|
19
|
-
[[3], [1, 2, 3, 4], [1, 2, 4], [4]],
|
20
|
-
[[1, 2, 4], [2], [1, 2, 3, 4], [1]],
|
21
|
-
[[1, 2, 3], [1, 2, 4], [4], [3]],
|
22
|
-
[[4], [3, 4], [1], [1, 2, 3, 4]]
|
23
|
-
]
|
24
|
-
|
25
|
-
describe NSudoku do
|
26
|
-
|
27
|
-
before do
|
28
|
-
@logic = NSudoku::Logic.new(EXAMPLE)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "can generate reverse of sudoku" do
|
32
|
-
@logic.revers[0][1].should eql([1, 2, 3, 4])
|
33
|
-
@logic.revers[3][3].inspect
|
34
|
-
end
|
35
|
-
|
36
|
-
it "can get result" do
|
37
|
-
@logic.sudoku.should eql(EXAMPLE)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "can erase that same elements in column" do
|
41
|
-
@logic.erase_elements_column(0, 0).revers[0][1].should eql([2, 3, 4])
|
42
|
-
end
|
43
|
-
|
44
|
-
it "can erase that same elements in row" do
|
45
|
-
@logic.erase_elements_row(2, 2).revers[1][2].should eql([1, 2, 3])
|
46
|
-
end
|
47
|
-
|
48
|
-
it "can erase that same elements in block" do
|
49
|
-
@logic.erase_elements_block(2, 2).revers[3][3].should eql([1, 2, 3])
|
50
|
-
end
|
51
|
-
|
52
|
-
it "can choos only one value in elements for vertical situation" do
|
53
|
-
@logic.revers = REVERS
|
54
|
-
@logic.one_element_vertical(2).revers[1][2].should eql([3])
|
55
|
-
end
|
56
|
-
|
57
|
-
it "can choos only one value in elements for horizontal situation" do
|
58
|
-
@logic.revers = REVERS
|
59
|
-
@logic.one_element_horizontal(2).revers[1][2].should eql([3])
|
60
|
-
end
|
61
|
-
|
62
|
-
it "can choos only one value in elements for block situation" do
|
63
|
-
@logic.revers = REVERS
|
64
|
-
@logic.one_element_block(2).revers[1][2].should eql([3])
|
65
|
-
end
|
66
|
-
|
67
|
-
it "can choos only two values in elements for block situation" do
|
68
|
-
@logic.revers = REVERS
|
69
|
-
@logic.two_elements_block(2).revers[2][0].should eql([1, 2])
|
70
|
-
@logic.revers[2][1].should eql([1, 2])
|
71
|
-
end
|
72
|
-
|
73
|
-
it "can choos only two values in elements for vertical situation" do
|
74
|
-
@logic.revers = REVERS
|
75
|
-
@logic.two_elements_column(0).revers[1][0].should eql([1, 2])
|
76
|
-
@logic.revers[2][0].should eql([1, 2])
|
77
|
-
end
|
78
|
-
|
79
|
-
it "can choos only two values in elements for horizontal situation" do
|
80
|
-
@logic.revers = REVERS
|
81
|
-
@logic.two_elements_row(2).revers[2][0].should eql([1, 2])
|
82
|
-
@logic.revers[2][1].should eql([1, 2])
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|