-
Notifications
You must be signed in to change notification settings - Fork 0
/
board.rb
149 lines (117 loc) · 2.78 KB
/
board.rb
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
require './global'
require './sudoku_row'
class Board
attr_reader :matrix, :lines, :columns, :squares
def initialize matrix = nil
if matrix.nil?
matrix = Array.new(Size) { SudokuRow.new(Size) { 0 } }
else
matrix.each_with_index { |l, i| matrix[i] = SudokuRow.new(l) }
end
@matrix = matrix
end
def lines
@matrix
end
def [] index
@matrix[index]
end
def columns
m = []
@matrix.transpose.each { |l| m << SudokuRow.new(l) }
m
end
def all_values
@matrix.flatten
end
def get index
all_values[index]
end
def set index, value
line = index / Size
col = index % Size
@matrix[line][col] = value
end
def get_peers index
line = index / Size
col = index % Size
square = line / Sqrt * Sqrt + col / Sqrt
p = []
lines[line].each { |e| p << e }
columns[col].each { |e| p << e }
squares[square].each { |e| p << e }
p = p.uniq.select { |i| (1..Size).include? i }
p.sort
end
def shuffle!
@matrix.shuffle!
self
end
def swap_lines a, b
lines[a], lines[b] = lines[b], lines[a]
end
def fill_valid
Size.times { |i| Size.times { |j| @matrix[i][j] = (i + j) % Size + 1 } }
swap_lines 1, 3
swap_lines 2, 6
swap_lines 5, 7
self
end
def valid?
lines.each { |i| return false unless i.valid? }
columns.each { |i| return false unless i.valid? }
squares.each { |i| return false unless i.valid? }
return true
end
def possible?
lines.each { |i| return false if i.repeated? }
columns.each { |i| return false if i.repeated? }
squares.each { |i| return false if i.repeated? }
return true
end
def squares
m = Array.new
Size.times do |i|
l = i/Sqrt * Sqrt
min = (i % Sqrt) * Sqrt
range = min..(min + 2)
m << SudokuRow.new(@matrix[l][range] +
@matrix[l + 1][range] +
@matrix[l + 2][range])
end
m
end
def show
lines.each { |s| puts s.join(" ") }
end
def show_pretty
puts
lines.each_with_index do |l, i|
l.each_slice(Sqrt) do |s|
s = s.replace 0, '.'
print s.join(" ") + " "
end
puts
puts if i % Sqrt == Sqrt - 1
end
nil
end
def self.from_file difficulty, index = nil
r = Random.new
filename = "data/board/#{difficulty.to_s}.txt"
f = File.open(filename)
n_patterns = f.readline.chomp.to_i
selected = index.nil? ? r.rand(n_patterns) : index
# read until the selected pattern
((Size + 1) * selected).times { f.readline }
s = ''
f.readline
Size.times { s << f.readline.chomp }
f.close
board = Board.new
s.chars.each_with_index do |c, i|
board.set i, c.to_i if (1..Size).include? c.to_i
end
board
end
end