algos 0.6.8

A collection of algorithms in Rust
Documentation
//! Module for generating the power set (all subsets) of a slice using binary representation.
//!
//! This module provides:
//! - An eager function `power_set` that returns all subsets as a Vec<Vec<T>>.
//! - A lazy iterator `PowerSet` (with helper function `power_set_iter`) that yields subsets one by one.
//!
//! The subsets are generated by interpreting the numbers 0..2ⁿ as bit masks, where the i‑th bit
//! indicates whether the i‑th element is included.
//!
//! # Examples
//!
//! Eager usage:
//!
//! ```
//! use algos::cs::combinatorial::subset_gen::power_set;
//!
//! let items = vec![1, 2, 3];
//! let subsets = power_set(&items);
//! // For 3 elements, there are 2^3 = 8 subsets.
//! assert_eq!(subsets.len(), 8);
//! assert!(subsets.contains(&vec![]));
//! assert!(subsets.contains(&vec![1, 2, 3]));
//! ```
//!
//! Lazy usage:
//!
//! ```
//! use algos::cs::combinatorial::subset_gen::power_set_iter;
//!
//! let items = vec!['a', 'b'];
//! let subsets: Vec<_> = power_set_iter(&items).collect();
//! assert_eq!(subsets.len(), 4);
//! assert!(subsets.contains(&vec![]));
//! assert!(subsets.contains(&vec!['a', 'b']));
//! ```

/// Returns all possible subsets of the given slice.
pub fn power_set<T: Clone>(elements: &[T]) -> Vec<Vec<T>> {
    let n = elements.len();
    let total = 1 << n;
    let mut result = Vec::with_capacity(total);

    for mask in 0..total {
        let mut subset = Vec::new();
        for (i, item) in elements.iter().enumerate() {
            if (mask & (1 << i)) != 0 {
                subset.push(item.clone());
            }
        }
        result.push(subset);
    }
    result
}

/// An iterator that lazily generates all subsets of a slice.
pub struct PowerSet<'a, T> {
    elements: &'a [T],
    current: usize,
    total: usize,
}

impl<'a, T> PowerSet<'a, T> {
    fn new(elements: &'a [T]) -> Self {
        PowerSet {
            elements,
            current: 0,
            total: 1 << elements.len(),
        }
    }
}

impl<T: Clone> Iterator for PowerSet<'_, T> {
    type Item = Vec<T>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current >= self.total {
            return None;
        }

        let mut subset = Vec::new();
        for (i, item) in self.elements.iter().enumerate() {
            if (self.current & (1 << i)) != 0 {
                subset.push(item.clone());
            }
        }

        self.current += 1;
        Some(subset)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.total - self.current;
        (remaining, Some(remaining))
    }
}

/// Returns an iterator that lazily generates all subsets of the given slice.
pub fn power_set_iter<T>(elements: &[T]) -> PowerSet<T> {
    PowerSet::new(elements)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_power_set_empty() {
        let empty: Vec<i32> = vec![];
        let subsets = power_set(&empty);
        assert_eq!(subsets.len(), 1);
        assert_eq!(subsets[0], vec![]);
    }

    #[test]
    fn test_power_set_single() {
        let items = vec![42];
        let subsets = power_set(&items);
        assert_eq!(subsets.len(), 2);
        assert!(subsets.contains(&vec![]));
        assert!(subsets.contains(&vec![42]));
    }

    #[test]
    fn test_power_set_multiple() {
        let items = vec![1, 2, 3];
        let subsets = power_set(&items);
        assert_eq!(subsets.len(), 8);
        assert!(subsets.contains(&vec![]));
        assert!(subsets.contains(&vec![1]));
        assert!(subsets.contains(&vec![2]));
        assert!(subsets.contains(&vec![3]));
        assert!(subsets.contains(&vec![1, 2]));
        assert!(subsets.contains(&vec![1, 3]));
        assert!(subsets.contains(&vec![2, 3]));
        assert!(subsets.contains(&vec![1, 2, 3]));
    }

    #[test]
    fn test_power_set_iter() {
        let items = vec!['a', 'b'];
        let subsets: Vec<_> = power_set_iter(&items).collect();
        assert_eq!(subsets.len(), 4);
        assert!(subsets.contains(&vec![]));
        assert!(subsets.contains(&vec!['a']));
        assert!(subsets.contains(&vec!['b']));
        assert!(subsets.contains(&vec!['a', 'b']));
    }

    #[test]
    fn test_size_hint() {
        let items = vec![1, 2, 3];
        let mut iter = power_set_iter(&items);
        assert_eq!(iter.size_hint(), (8, Some(8)));
        iter.next();
        assert_eq!(iter.size_hint(), (7, Some(7)));
    }
}