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
|
use super::Puzzle;
use rand::Rng;
impl Puzzle {
/// O(N)
pub fn max_queen_col(&mut self) -> usize {
let (mut max_attack, mut max_queens) = (i32::MIN, Vec::new());
for col in 0..self.N {
let attacks = self.attacks(col, self.in_col[col]);
if attacks > max_attack {
max_attack = attacks;
max_queens.clear();
}
if attacks == max_attack {
max_queens.push(col);
}
}
if max_queens.len() > 1 {
return max_queens[self.rng.gen_range(0..max_queens.len())];
}
return max_queens[0];
}
/// O(N)
pub fn min_col_row(&mut self, colI: usize) -> usize {
let (mut min_row, mut min_ind) = (i32::MAX, Vec::new());
for row in 0..self.N {
let attacks = self.attacks(colI, row);
if attacks < min_row {
min_row = attacks;
min_ind.clear();
}
if attacks == min_row {
min_ind.push(row);
}
}
if min_ind.len() > 1 {
return min_ind[self.rng.gen_range(0..min_ind.len())];
}
return min_ind[0];
}
/// O(1)
pub fn update(&mut self, colI: usize, val: i32) {
assert!(colI < self.N && (val == 1 || val == -1), "Bad arguments to update: {} {}!", colI, val);
self.per_row[self.in_col[colI]] += val;
self.per_d1[colI + self.N - 1 - self.in_col[colI]] += val;
self.per_d2[colI + self.in_col[colI]] += val;
if val < 0 {
// Sanity check when removing a queen
self.in_col[colI] = self.N;
}
}
/// O(1)
pub fn move_queen(&mut self, colI: usize, rowI: usize) {
if rowI == self.in_col[colI] { return; }
self.update(colI, -1);
self.in_col[colI] = rowI;
self.update(colI, 1);
}
}
#[test]
fn test_max_queen_col() {
let mut e1 = Puzzle::example1();
assert_eq!(e1.max_queen_col(), 2, "Bad max_queen_col on single max!");
let mut e2 = Puzzle::example2();
let mut got = [false; 4];
for _ in 0..10000 {
got[e2.max_queen_col()] = true;
}
assert!(got.iter().all(|&x| x), "Bad max_queen_col on multiple max!");
}
#[test]
fn test_min_col_row() {
let mut e1 = Puzzle::example1();
let mut got = [false; 4];
for _ in 0..10000 {
got[e1.min_col_row(0)] = true;
}
assert!(got[0] && !got[1] && got[2] && got[3], "Bad min_col_row on multiple (3) min!");
got = [false; 4];
for _ in 0..10000 {
got[e1.min_col_row(2)] = true;
}
assert!(got[0] && !got[1] && got[2] && !got[3], "Bad min_col_row on multiple (2) min!");
let mut e2 = Puzzle::example2();
assert_eq!(e2.min_col_row(0), 3, "Bad min_col_row on single min!");
assert_eq!(e2.min_col_row(3), 1, "Bad min_col_row on single min!");
}
#[test]
fn test_update() {
let mut e1 = Puzzle::example1();
e1.update(0, -1);
e1.update(2, -1);
e1.in_col[0] = 3;
e1.update(0, 1);
e1.in_col[2] = 1;
e1.update(2, 1);
let e1s = Puzzle::example1();
assert_eq!(e1, e1s, "Bad update!");
}
#[test]
fn test_move_queen() {
let e1s = Puzzle::example1();
let mut e1 = Puzzle::example1();
e1.move_queen(0, 0);
e1.move_queen(0, 3);
assert_eq!(e1, e1s, "Bad move_queen identity!");
let mut e1 = Puzzle::example1();
e1.move_queen(2, 0);
e1.move_queen(2, 1);
assert_eq!(e1, e1s, "Bad move_queen identity on moved max!");
let mut e1 = Puzzle::example1();
e1.move_queen(0, 0);
e1.move_queen(2, 2);
let e2 = Puzzle::example2();
assert_eq!(e1, e2, "Bad move_queen on changed maxes!");
}
|