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
use super::candidate_set::CandidateSet;
use super::index::ALL_GROUPINGS;
use std::ops::{Deref, DerefMut};
pub struct Sudoku([CandidateSet; 81]);
const ALL_POSSIBLE: usize = (1 << 9) - 1;
fn valid_group<T: Iterator<Item = usize>>(sudoku: &Sudoku, mut iter: T) -> bool {
let mut s = 0;
let mut a = 0;
iter.all(|i| {
let m = sudoku[i].get_candidates();
a |= m;
if sudoku[i].is_solved() {
if (s & m) != 0 {
false
} else {
s |= m;
true
}
} else {
true
}
}) && a == ALL_POSSIBLE
}
impl Deref for Sudoku {
type Target = [CandidateSet];
fn deref(&self) -> &[CandidateSet] {
&self.0
}
}
impl DerefMut for Sudoku {
fn deref_mut(&mut self) -> &mut [CandidateSet] {
&mut self.0
}
}
impl Sudoku {
pub fn new(positions: [CandidateSet; 81]) -> Self {
Sudoku(positions)
}
pub fn num_solved(&self) -> usize {
self.0.iter().filter(|x| x.is_solved()).count()
}
pub fn is_solved(&self) -> bool {
self.0.iter().all(|x| x.is_solved())
}
pub fn oneline(&self) -> String {
self.0
.iter()
.map(|p| {
let v = p.value().unwrap_or(0);
match v {
0 => ".".to_string(),
_ => v.to_string(),
}
})
.collect::<Vec<String>>()
.join("")
}
pub fn is_valid(&self) -> bool {
ALL_GROUPINGS
.iter()
.all(|g| (0..9).all(|idx| valid_group(self, g.iter(idx))))
}
}