Skip to content

power_multiset: powerset where repeated items don't produce repeated subsets #1074

@Pr0methean

Description

@Pr0methean

It would be nice to have a version of the following as a convenient, efficient library function rather than having had to roll my own:

#[inline]
fn power_multiset<T: PartialEq + Ord + Copy>(multiset: &mut Vec<T>) -> Vec<Vec<T>> {
    let mut result = Vec::new();
    multiset.sort_unstable(); // Sort to handle duplicates more easily

    #[inline]
    fn generate_subsets<T: PartialEq + Copy>(
        current_subset: &mut Vec<T>,
        remaining_elements: &mut Vec<T>,
        all_subsets: &mut Vec<Vec<T>>,
    ) {
        // Add the current subset to the result
        all_subsets.push(current_subset.clone());

        if remaining_elements.is_empty() {
            return;
        }

        let mut i = 0;
        while i < remaining_elements.len() {
            let element = remaining_elements.remove(i);
            current_subset.push(element);

            generate_subsets(current_subset, remaining_elements, all_subsets);

            // Backtrack: add the element back and remove from current_subset
            current_subset.pop();
            remaining_elements.insert(i, element);

            // Skip duplicate elements to avoid redundant subsets
            while i < remaining_elements.len() && remaining_elements[i] == element {
                i += 1;
            }
        }
    }

    let mut current_subset = Vec::new();
    generate_subsets(&mut current_subset, multiset, &mut result);
    for subset in result.iter_mut() {
        subset.sort_unstable();
    }
    result.sort_unstable();
    result.dedup();
    result
}

    #[test]
    fn test_power_multiset() {
        let mut multiset = vec![2, 2, 3, 3, 5];
        let power_multiset = power_multiset(&mut multiset);
        println!("{:?}", power_multiset);
        assert_eq!(power_multiset.len(), 18);
        assert!(power_multiset.contains(&vec![]));
        assert!(power_multiset.contains(&vec![2]));
        assert!(power_multiset.contains(&vec![2, 2]));
        assert!(power_multiset.contains(&vec![3]));
        assert!(power_multiset.contains(&vec![2, 3]));
        assert!(power_multiset.contains(&vec![2, 2, 3]));
        assert!(power_multiset.contains(&vec![3, 3]));
        assert!(power_multiset.contains(&vec![2, 3, 3]));
        assert!(power_multiset.contains(&vec![2, 2, 3, 3]));
        assert!(power_multiset.contains(&vec![5]));
        assert!(power_multiset.contains(&vec![2, 5]));
        assert!(power_multiset.contains(&vec![2, 2, 5]));
        assert!(power_multiset.contains(&vec![3, 5]));
        assert!(power_multiset.contains(&vec![2, 3, 5]));
        assert!(power_multiset.contains(&vec![2, 2, 3, 5]));
        assert!(power_multiset.contains(&vec![3, 3, 5]));
        assert!(power_multiset.contains(&vec![2, 3, 3, 5]));
        assert!(power_multiset.contains(&vec![2, 2, 3, 3, 5]));
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions