sudoku_solver/utils/
cellset.rs

1use 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}