sudoku/
bitset.rs

1//! Generic, fixed-size bitsets
2//!
3//! Sudoku strategies deal with sets of various things such as [`Digit`s](crate::board::Digit) and [`House`s](crate::board::House) a lot.
4//! Efficient storage is important for maximal performance, but it should not be possible
5//! to confuse bitmasks for different things. This module contains type-safe, space-efficient
6//! fixed-length bitsets for digits and various sudoku positions.
7
8use crate::board::{Cell, Col, Digit, House, Line, Position, Row};
9use crate::helper::Unsolvable;
10use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};
11
12/// Generic, fixed-size bitset
13#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14pub struct Set<T: SetElement>(pub(crate) T::Storage);
15
16/// Iterator over the elements contained in a [`Set`]
17#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct Iter<T: SetElement>(T::Storage);
19
20impl<T: SetElement> IntoIterator for Set<T>
21where
22    Iter<T>: Iterator,
23{
24    type Item = <Iter<T> as Iterator>::Item;
25    type IntoIter = Iter<T>;
26
27    fn into_iter(self) -> Self::IntoIter {
28        Iter(self.0)
29    }
30}
31
32///////////////////////////////////////////////////////////////////////////////////////////////
33//                                  Bitops
34///////////////////////////////////////////////////////////////////////////////////////////////
35
36macro_rules! impl_binary_bitops {
37    ( $( $trait:ident, $fn_name:ident);* $(;)* ) => {
38        $(
39            impl<T: SetElement> $trait for Set<T> {
40                type Output = Self;
41
42                #[inline(always)]
43                fn $fn_name(self, other: Self) -> Self {
44                    Set(
45                        $trait::$fn_name(self.0, other.0)
46                    )
47                }
48            }
49
50            impl<T: SetElement> $trait<T> for Set<T> {
51                type Output = Self;
52
53                #[inline(always)]
54                fn $fn_name(self, other: T) -> Self {
55                    $trait::$fn_name(self, other.as_set())
56                }
57            }
58        )*
59    };
60}
61
62macro_rules! impl_bitops_assign {
63    ( $( $trait:ident, $fn_name:ident);* $(;)* ) => {
64        $(
65            impl<T: SetElement> $trait for Set<T> {
66                #[inline(always)]
67                fn $fn_name(&mut self, other: Self) {
68                    $trait::$fn_name(&mut self.0, other.0)
69                }
70            }
71
72            impl<T: SetElement> $trait<T> for Set<T> {
73                #[inline(always)]
74                fn $fn_name(&mut self, other: T) {
75                    $trait::$fn_name(self, other.as_set())
76                }
77            }
78        )*
79    };
80}
81
82impl_binary_bitops!(
83    BitAnd, bitand;
84    BitOr, bitor;
85    BitXor, bitxor;
86);
87
88impl_bitops_assign!(
89    BitAndAssign, bitand_assign;
90    BitOrAssign, bitor_assign;
91    BitXorAssign, bitxor_assign;
92);
93
94impl<T: SetElement> Not for Set<T>
95where
96    Self: PartialEq + Copy,
97{
98    type Output = Self;
99    fn not(self) -> Self {
100        Self::ALL.without(self)
101    }
102}
103
104/// Potential return value for [`Set::unique`]
105#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
106pub struct Empty;
107
108impl From<Empty> for Unsolvable {
109    fn from(_: Empty) -> Unsolvable {
110        Unsolvable
111    }
112}
113
114impl<T: SetElement> Set<T>
115where
116    // TODO: properly implement the traits for Set and Iter
117    //       bounded on T::Storage, not on T (which derive does)
118    Self: PartialEq + Copy,
119{
120    /// Set containing all possible elements
121    pub const ALL: Set<T> = Set(<T as SetElement>::ALL);
122
123    /// Empty Set
124    pub const NONE: Set<T> = Set(<T as SetElement>::NONE);
125
126    /// Construct a bitset from a raw integer.
127    ///
128    /// # Panic
129    /// Panics, if the integer contains bits above [`Set::ALL`]
130    pub fn from_bits(mask: T::Storage) -> Self {
131        assert!(mask <= <T as SetElement>::ALL);
132        Set(mask)
133    }
134
135    /// Return the raw integer backing the set.
136    pub fn bits(self) -> T::Storage {
137        self.0
138    }
139
140    /// Returns the set of elements in this set, that aren't present in `other`.
141    pub fn without(self, other: Self) -> Self {
142        Set(self.0 & !other.0)
143    }
144
145    /// Deletes all elements from this set that are present in `other`.
146    pub fn remove(&mut self, other: Self) {
147        self.0 &= !other.0;
148    }
149
150    /// Checks if `self` and `other` contain any common element.
151    pub fn overlaps(&self, other: Self) -> bool {
152        *self & other != Set::NONE
153    }
154
155    /// Checks if `self` contains `other`.
156    pub fn contains(&self, other: impl Into<Self>) -> bool {
157        let other = other.into();
158        *self & other == other
159    }
160
161    /// Returns the number of elements in this set.
162    pub fn len(&self) -> u8 {
163        T::count_possibilities(self.0) as u8
164    }
165
166    /// Checks whether this set contains any element.
167    pub fn is_empty(&self) -> bool {
168        self.len() == 0
169    }
170
171    /// Checks whether this set contains all possible elements.
172    pub fn is_full(&self) -> bool {
173        *self == Self::ALL
174    }
175
176    /// Returns the only element in this set, iff only 1 element exists.
177    /// If no elements exist, it returns `Err(Empty)`.
178    /// If more than 1 element exists, it returns `Ok(None)`.
179    pub fn unique(self) -> Result<Option<T>, Empty>
180    where
181        Iter<T>: Iterator<Item = T>,
182    {
183        match self.len() {
184            1 => {
185                let element = self.into_iter().next();
186                debug_assert!(element.is_some());
187                Ok(element)
188            }
189            0 => Err(Empty),
190            _ => Ok(None),
191        }
192    }
193
194    /// Returns one of the elements in this set.
195    /// It is equivalent to `self.into_iter().next().unwrap()`
196    ///
197    /// # Panic
198    /// Panics, if the set is empty
199    #[allow(unused)]
200    pub(crate) fn one_possibility(self) -> T
201    where
202        Iter<T>: Iterator<Item = T>,
203    {
204        self.into_iter().next().expect("mask is empty")
205    }
206}
207
208///////////////////////////////////////////////////////////////////////////////////////////////
209
210/// Trait for types that can be stored in a [`Set`]
211#[allow(missing_docs)]
212pub trait SetElement: Sized + set_element::Sealed {
213    const ALL: Self::Storage;
214    const NONE: Self::Storage;
215
216    type Storage: BitAnd<Output = Self::Storage>
217        + BitAndAssign
218        + BitOr<Output = Self::Storage>
219        + BitOrAssign
220        + BitXor<Output = Self::Storage>
221        + BitXorAssign
222        + Not<Output = Self::Storage>
223        + PartialOrd
224        + std::fmt::Binary
225        + Copy;
226
227    fn count_possibilities(set: Self::Storage) -> u32;
228    fn as_set(self) -> Set<Self>;
229}
230mod set_element {
231    use super::*;
232    pub trait Sealed {}
233
234    macro_rules! impl_sealed {
235        ($($type:ty),*) => {
236            $(
237                impl Sealed for $type {}
238            )*
239        };
240    }
241
242    impl_sealed! {
243        Cell, Digit, Row, Col, House, Line, Position<Line>, Position<House>
244    }
245}
246
247// returns a bitmask with the lowest `bitset_size` number of bits set
248const fn n_bits_set(bitset_size: u8) -> u128 {
249    (1 << bitset_size) - 1
250}
251
252macro_rules! impl_setelement {
253    ( $( $type:ty => $storage_ty:ty, $bitset_size:expr),* $(,)* ) => {
254        $(
255            impl SetElement for $type {
256                // try_into() would be better to avoid silent truncation
257                // but trait methods can't be constified yet.
258                const ALL: $storage_ty = n_bits_set($bitset_size) as $storage_ty;
259                const NONE: $storage_ty = 0;
260
261                type Storage = $storage_ty;
262
263                fn count_possibilities(set: Self::Storage) -> u32 {
264                    set.count_ones()
265                }
266
267                fn as_set(self) -> Set<Self> {
268                    Set(1 << self.as_index() as u8)
269                }
270            }
271
272            impl $type {
273                /// Returns a `Set<Self>` with the bit corresponding to this element set.
274                pub fn as_set(self) -> Set<Self> {
275                    SetElement::as_set(self)
276                }
277            }
278        )*
279    };
280}
281
282impl_setelement!(
283    // 81 cells
284    Cell => u128, 81,
285    // 9 digits
286    Digit => u16, 9,
287
288    // 9 of each house
289    //Row => u16, 9,
290    //Col => u16, 9,
291    //Block => u16, 9,
292    Line => u32, 18,      // both Rows and Cols
293    House => u32, 27, // Rows, Cols, Blocks
294
295    // 9 positions per house
296    //Position<Row> => u16, 9,
297    //Position<Col> => u16, 9,
298    Position<Line> => u16, 9,
299    Position<House> => u16, 9,
300    // 27 positions per chute
301    //Position<Band> => u32, 27,
302    //Position<Stack> => u32, 27,
303    //Position<Chute> => u32, 27,
304);
305
306macro_rules! impl_iter_for_setiter {
307    ( $( $type:ty => $constructor:expr ),* $(,)* ) => {
308        $(
309            impl Iterator for Iter<$type> {
310                type Item = $type;
311
312                fn next(&mut self) -> Option<Self::Item> {
313                    debug_assert!(self.0 <= <Set<$type>>::ALL.0, "{:o}", self.0);
314                    if self.0 == 0 {
315                        return None;
316                    }
317                    let lowest_bit = self.0 & (!self.0 + 1);
318                    let bit_pos = lowest_bit.trailing_zeros() as u8;
319                    self.0 ^= lowest_bit;
320                    Some($constructor(bit_pos))
321                }
322            }
323        )*
324    };
325}
326
327// can't do this generically
328impl_iter_for_setiter!(
329    Cell => Cell::new,
330    Digit => Digit::from_index,
331    Line => Line::new,
332    House => House::new,
333    //Position<Row> => Position::new,
334    //Position<Col> => Position::new,
335    Position<Line> => Position::new,
336    Position<House> => Position::new,
337    //Position<Band> => Position::new,
338    //Position<Stack> => Position::new,
339    //Position<Chute> => Position::new,
340);
341
342use std::fmt;
343impl<T: SetElement> fmt::Binary for Set<T> {
344    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
345        write!(f, "{:b}", self.0)
346    }
347}