sudoku_solver/utils/
cellset.rs1use arrayvec::ArrayVec;
2use itertools::Itertools;
3
4use crate::sudoku::{CellIndex, Sudoku};
5
6use std::cell::OnceCell;
7use std::iter::{Copied, FromIterator};
8use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Deref, DerefMut, Sub, SubAssign};
9use std::usize;
10
11#[derive(Debug, Clone)]
12pub struct CellSet {
13 bitset: u128,
14 cells: OnceCell<ArrayVec<CellIndex, 81>>,
15}
16
17impl CellSet {
18 pub fn new() -> Self {
19 CellSet {
20 bitset: 0,
21 cells: OnceCell::new(),
22 }
23 }
24
25 pub fn from_bitset(bitset: u128) -> Self {
26 CellSet {
27 bitset,
28 cells: OnceCell::new(),
29 }
30 }
31
32 pub fn from_cells(cell_positions: Vec<CellIndex>) -> Self {
33 let mut set = Self::new();
34 for cell in &cell_positions {
35 set.add(*cell);
36 }
37 let array = ArrayVec::from_iter(cell_positions);
38 set.cells = array.into();
39 set
40 }
41
42 pub fn is_empty(&self) -> bool {
43 self.bitset == 0
44 }
45
46 pub fn size(&self) -> usize {
47 self.bitset.count_ones() as usize
48 }
49
50 pub fn add(&mut self, cell: CellIndex) {
51 self.cells.take();
52 self.bitset |= 1 << cell;
53 }
54
55 pub fn has(&self, cell: CellIndex) -> bool {
56 (self.bitset & (1 << cell)) != 0
57 }
58
59 pub fn delete(&mut self, cell: CellIndex) {
60 self.cells.take();
61 self.bitset &= !(1 << cell);
62 }
63
64 pub fn clear(&mut self) {
65 self.cells.take();
66 self.bitset = 0;
67 }
68
69 pub fn is_subset_of(&self, other: &Self) -> bool {
70 (self.bitset & other.bitset) == self.bitset
71 }
72
73 pub fn union_multiple<'a>(iter: impl Iterator<Item = &'a Self>) -> Self {
74 let mut union = Self::new();
75 for set in iter {
76 union.bitset |= set.bitset;
77 }
78 union
79 }
80
81 pub fn intersection_multiple<'a>(mut iter: impl Iterator<Item = &'a Self>) -> Self {
82 let first = iter.next().unwrap();
83 let mut intersection = Self::from_bitset(first.bitset);
84 for set in iter {
85 intersection.bitset &= set.bitset;
86 }
87 intersection
88 }
89
90 pub fn iter(&self) -> Copied<std::slice::Iter<CellIndex>> {
91 self.cells
92 .get_or_init(|| {
93 let mut cells = ArrayVec::new();
94 if !self.is_empty() {
95 for idx in (0..81).step_by(9) {
96 let bits = ((self.bitset >> idx) & 0x1FF) as usize;
97 if bits == 0 {
98 continue;
99 }
100 for i in 0..9 {
101 if (bits & (1 << i)) != 0 {
102 cells.push(idx + i);
103 }
104 }
105 }
106 }
107 cells
108 })
109 .iter()
110 .copied()
111 }
112
113 pub fn to_string(&self, sudoku: &Sudoku) -> String {
114 self.iter().map(|cell| sudoku.get_cell_name(cell)).join(",")
115 }
116}
117
118impl SubAssign<&CellSet> for CellSet {
119 fn sub_assign(&mut self, other: &CellSet) {
120 self.cells.take();
121 self.bitset &= !other.bitset;
122 }
123}
124
125impl Sub for &CellSet {
126 type Output = CellSet;
127
128 fn sub(self, other: Self) -> Self::Output {
129 CellSet::from_bitset(self.bitset & !other.bitset)
130 }
131}
132
133impl BitOrAssign<&CellSet> for CellSet {
134 fn bitor_assign(&mut self, other: &CellSet) {
135 self.cells.take();
136 self.bitset |= other.bitset;
137 }
138}
139
140impl BitOr for &CellSet {
141 type Output = CellSet;
142
143 fn bitor(self, other: Self) -> Self::Output {
144 CellSet::from_bitset(self.bitset | other.bitset)
145 }
146}
147
148impl BitAndAssign<&CellSet> for CellSet {
149 fn bitand_assign(&mut self, other: &CellSet) {
150 self.cells.take();
151 self.bitset &= other.bitset;
152 }
153}
154
155impl BitAnd for &CellSet {
156 type Output = CellSet;
157
158 fn bitand(self, other: Self) -> Self::Output {
159 CellSet::from_bitset(self.bitset & other.bitset)
160 }
161}
162
163impl PartialEq for CellSet {
164 fn eq(&self, other: &Self) -> bool {
165 self.bitset == other.bitset
166 }
167}
168
169impl Eq for CellSet {}
170
171impl<'a> IntoIterator for &'a CellSet {
172 type Item = CellIndex;
173 type IntoIter = Copied<std::slice::Iter<'a, CellIndex>>;
174
175 fn into_iter(self) -> Self::IntoIter {
176 self.iter()
177 }
178}
179
180#[derive(Debug, Clone)]
181pub struct NamedCellSet {
182 name: String,
183 idx: usize,
184 cells: CellSet,
185}
186
187impl NamedCellSet {
188 pub fn new(name: String, idx: usize) -> Self {
189 NamedCellSet {
190 name,
191 idx,
192 cells: CellSet::new(),
193 }
194 }
195
196 pub fn from_cellset(source: &NamedCellSet, cells: CellSet) -> Self {
197 NamedCellSet {
198 name: source.name().to_string(),
199 cells,
200 idx: source.idx(),
201 }
202 }
203
204 pub fn name(&self) -> &str {
205 &self.name
206 }
207
208 pub fn idx(&self) -> usize {
209 self.idx
210 }
211}
212
213impl Deref for NamedCellSet {
214 type Target = CellSet;
215
216 fn deref(&self) -> &Self::Target {
217 &self.cells
218 }
219}
220
221impl DerefMut for NamedCellSet {
222 fn deref_mut(&mut self) -> &mut Self::Target {
223 &mut self.cells
224 }
225}
226
227impl BitOr for &NamedCellSet {
228 type Output = CellSet;
229
230 fn bitor(self, other: Self) -> Self::Output {
231 &self.cells | &other.cells
232 }
233}
234
235impl BitAnd for &NamedCellSet {
236 type Output = CellSet;
237
238 fn bitand(self, other: Self) -> Self::Output {
239 &self.cells & &other.cells
240 }
241}
242
243impl BitOr<&CellSet> for &NamedCellSet {
244 type Output = CellSet;
245
246 fn bitor(self, other: &CellSet) -> Self::Output {
247 &self.cells | other
248 }
249}
250
251impl BitAnd<&CellSet> for &NamedCellSet {
252 type Output = CellSet;
253
254 fn bitand(self, other: &CellSet) -> Self::Output {
255 &self.cells & other
256 }
257}
258
259impl PartialEq for NamedCellSet {
260 fn eq(&self, other: &Self) -> bool {
261 self.cells == other.cells
262 }
263}
264
265#[cfg(test)]
266mod tests {
267 use super::*;
268
269 #[test]
270 fn test_cellset() {
271 let mut set = CellSet::new();
272 assert!(set.is_empty());
273 assert_eq!(set.size(), 0);
274
275 set.add(0);
276 assert!(!set.is_empty());
277 assert_eq!(set.size(), 1);
278
279 set.add(1);
280 assert_eq!(set.size(), 2);
281
282 set.delete(0);
283 assert_eq!(set.size(), 1);
284
285 set.clear();
286 assert!(set.is_empty());
287 assert_eq!(set.size(), 0);
288
289 set.add(0);
290 set.add(1);
291 let mut other = CellSet::new();
292 other.add(0);
293 other.add(2);
294 set -= &other;
295 assert_eq!(set.size(), 1);
296 assert!(set.has(1));
297
298 set.clear();
299 set.add(0);
300 set.add(1);
301 let mut other = CellSet::new();
302 other.add(0);
303 other.add(2);
304 let union = &set | &other;
305 assert_eq!(union.size(), 3);
306 assert!(union.has(0));
307 assert!(union.has(1));
308 assert!(union.has(2));
309
310 let intersection = &set & &other;
311 assert_eq!(intersection.size(), 1);
312 assert!(intersection.has(0));
313 }
314}