1use alloc::vec::Vec;
2use std::fmt;
3use std::iter::FusedIterator;
4
5use super::combinations::{combinations, Combinations};
6use crate::adaptors::checked_binomial;
7use crate::size_hint::{self, SizeHint};
8
9#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
14pub struct Powerset<I: Iterator> {
15 combs: Combinations<I>,
16}
17
18impl<I> Clone for Powerset<I>
19where
20 I: Clone + Iterator,
21 I::Item: Clone,
22{
23 clone_fields!(combs);
24}
25
26impl<I> fmt::Debug for Powerset<I>
27where
28 I: Iterator + fmt::Debug,
29 I::Item: fmt::Debug,
30{
31 debug_fmt_fields!(Powerset, combs);
32}
33
34pub fn powerset<I>(src: I) -> Powerset<I>
36where
37 I: Iterator,
38 I::Item: Clone,
39{
40 Powerset {
41 combs: combinations(src, 0),
42 }
43}
44
45impl<I: Iterator> Powerset<I> {
46 fn increment_k(&mut self) -> bool {
48 if self.combs.k() < self.combs.n() || self.combs.k() == 0 {
49 self.combs.reset(self.combs.k() + 1);
50 true
51 } else {
52 false
53 }
54 }
55}
56
57impl<I> Iterator for Powerset<I>
58where
59 I: Iterator,
60 I::Item: Clone,
61{
62 type Item = Vec<I::Item>;
63
64 fn next(&mut self) -> Option<Self::Item> {
65 if let Some(elt) = self.combs.next() {
66 Some(elt)
67 } else if self.increment_k() {
68 self.combs.next()
69 } else {
70 None
71 }
72 }
73
74 fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
75 loop {
76 match self.combs.try_nth(n) {
77 Ok(item) => return Some(item),
78 Err(steps) => {
79 if !self.increment_k() {
80 return None;
81 }
82 n -= steps;
83 }
84 }
85 }
86 }
87
88 fn size_hint(&self) -> SizeHint {
89 let k = self.combs.k();
90 let (n_min, n_max) = self.combs.src().size_hint();
92 let low = remaining_for(n_min, k).unwrap_or(usize::MAX);
93 let upp = n_max.and_then(|n| remaining_for(n, k));
94 size_hint::add(self.combs.size_hint(), (low, upp))
95 }
96
97 fn count(self) -> usize {
98 let k = self.combs.k();
99 let (n, combs_count) = self.combs.n_and_count();
100 combs_count + remaining_for(n, k).unwrap()
101 }
102
103 fn fold<B, F>(self, mut init: B, mut f: F) -> B
104 where
105 F: FnMut(B, Self::Item) -> B,
106 {
107 let mut it = self.combs;
108 if it.k() == 0 {
109 init = it.by_ref().fold(init, &mut f);
110 it.reset(1);
111 }
112 init = it.by_ref().fold(init, &mut f);
113 for k in it.k() + 1..=it.n() {
115 it.reset(k);
116 init = it.by_ref().fold(init, &mut f);
117 }
118 init
119 }
120}
121
122impl<I> FusedIterator for Powerset<I>
123where
124 I: Iterator,
125 I::Item: Clone,
126{
127}
128
129fn remaining_for(n: usize, k: usize) -> Option<usize> {
130 (k + 1..=n).try_fold(0usize, |sum, i| sum.checked_add(checked_binomial(n, i)?))
131}