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
//! Module containing functions and structs for iterating subsets.
//!
//! Most users only need [`subsets`] method. See its documentation for examples.
use std::ops::RangeInclusive;
/// Constructs an iterator over subsets of given size.
///
/// For example the subsets of `[1, 2, 3]` are `[]`, `[1]`, `[2]`, `[1, 2]`, `[3]`, `[1, 3]`, `[2, 3]`, and `[1, 2, 3]`.
///
/// Note that the subsets are based on indices and hence this method doesn't do any kind of deduplication of the data.
/// For example subsets of array `[1, 1]` are `[]`, `[1]`, `[1]`, and `[1, 1]`.
///
/// See [`Subset`] for methods implemented on subsets.
///
/// # Examples
/// ```
/// # use comlib_math::subsets;
/// // Let's count the number of positive integers less than 10 that are divided by 2, 3, or 5, using
/// // inclusion-exclusion principle.
/// let primes = [2, 3, 5];
/// let result: i32 = subsets(primes.len())
/// .map(|subset| {
/// // We don't want to consider the empty subset
/// if subset.is_empty() {
/// return 0;
/// }
///
/// // Compute the value represented by the subset of primes
/// let num: i32 = subset.select(&primes).product();
/// // Compute the number of integers at most 100 that are divisible by num
/// let count = 100 / num;
///
/// if subset.len() % 2 == 1 {
/// // We add odd subsets
/// count
/// } else {
/// // and subtract even ones
/// -count
/// }
/// })
/// .sum();
/// assert_eq!(result, 74);
/// ```
pub fn subsets(n: usize) -> Subsets {
debug_assert!(n <= 64, "Subsets supports at most 64 element sets");
Subsets {
mask_iter: 0..=(u64::MAX >> (64 - n)),
}
}
/// Iterator over subsets.
///
/// Use [`subsets`] to construct. See its documentation for more usage examples.
#[derive(Debug, Clone)]
pub struct Subsets {
mask_iter: RangeInclusive<u64>,
}
impl Iterator for Subsets {
type Item = Subset;
fn next(&mut self) -> Option<Self::Item> {
self.mask_iter.next().map(|mask| Subset { mask })
}
fn size_hint(&self) -> (usize, Option<usize>) {
// Forward size hint to the inner iterator
self.mask_iter.size_hint()
}
}
/// Subset of some elements.
///
/// Use [`subsets`] to construct an iterator to get [`Subset`]s.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Subset {
/// Bit mask encoding the subset.
///
/// The lowest bit encodes item 0, the second lowest bit encodes item 1 etc.
pub mask: u64,
}
impl Subset {
/// Selects the elements belonging to the subset from the given iterator.
///
/// This is especially useful when iterating over all subsets of a list.
pub fn select<I: IntoIterator>(self, iter: I) -> SubsetIter<I::IntoIter> {
SubsetIter {
mask: self.mask,
iter: iter.into_iter(),
}
}
/// Checks whether the set is empty.
pub fn is_empty(self) -> bool {
self.mask == 0
}
/// Checks whether the set contains the given element.
pub fn contains(self, i: usize) -> bool {
(self.mask >> i) & 1 != 0
}
/// Returns the size of the subset.
pub fn len(self) -> usize {
self.mask.count_ones() as usize
}
}
/// An iterator selecting elements based on a subset.
///
/// This can be constructed using the [`select`] method on [`Subset`].
///
/// [`select`]: Subset::select
pub struct SubsetIter<I: Iterator> {
mask: u64,
iter: I,
}
impl<I: Iterator> Iterator for SubsetIter<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
while let Some(item) = self.iter.next() {
let selects = self.mask & 1 != 0;
self.mask >>= 1;
if selects {
return Some(item);
}
}
None
}
}