1
1
use std:: fmt;
2
+ use std:: usize;
2
3
use alloc:: vec:: Vec ;
3
4
4
5
use super :: combinations:: { Combinations , combinations} ;
6
+ use super :: size_hint;
5
7
6
8
/// An iterator to iterate through the powerset of the elements from an iterator.
7
9
///
@@ -10,28 +12,33 @@ use super::combinations::{Combinations, combinations};
10
12
#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
11
13
pub struct Powerset < I : Iterator > {
12
14
combs : Combinations < I > ,
15
+ // Iterator `position` (equal to count of yielded elements).
16
+ pos : usize ,
13
17
}
14
18
15
19
impl < I > Clone for Powerset < I >
16
20
where I : Clone + Iterator ,
17
21
I :: Item : Clone ,
18
22
{
19
- clone_fields ! ( combs) ;
23
+ clone_fields ! ( combs, pos ) ;
20
24
}
21
25
22
26
impl < I > fmt:: Debug for Powerset < I >
23
27
where I : Iterator + fmt:: Debug ,
24
28
I :: Item : fmt:: Debug ,
25
29
{
26
- debug_fmt_fields ! ( Powerset , combs) ;
30
+ debug_fmt_fields ! ( Powerset , combs, pos ) ;
27
31
}
28
32
29
33
/// Create a new `Powerset` from a clonable iterator.
30
34
pub fn powerset < I > ( src : I ) -> Powerset < I >
31
35
where I : Iterator ,
32
36
I :: Item : Clone ,
33
37
{
34
- Powerset { combs : combinations ( src, 0 ) }
38
+ Powerset {
39
+ combs : combinations ( src, 0 ) ,
40
+ pos : 0 ,
41
+ }
35
42
}
36
43
37
44
impl < I > Iterator for Powerset < I >
@@ -43,14 +50,34 @@ impl<I> Iterator for Powerset<I>
43
50
44
51
fn next ( & mut self ) -> Option < Self :: Item > {
45
52
if let Some ( elt) = self . combs . next ( ) {
53
+ self . pos = self . pos . saturating_add ( 1 ) ;
46
54
Some ( elt)
47
55
} else if self . combs . k ( ) < self . combs . n ( )
48
56
|| self . combs . k ( ) == 0
49
57
{
50
58
self . combs . reset ( self . combs . k ( ) + 1 ) ;
51
- self . combs . next ( )
59
+ self . combs . next ( ) . map ( |elt| {
60
+ self . pos = self . pos . saturating_add ( 1 ) ;
61
+ elt
62
+ } )
52
63
} else {
53
64
None
54
65
}
55
66
}
67
+
68
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
69
+ // Total bounds for source iterator.
70
+ let src_total = size_hint:: add_scalar ( self . combs . src ( ) . size_hint ( ) , self . combs . n ( ) ) ;
71
+
72
+ // Total bounds for self ( length(powerset(set) == 2 ^ length(set) )
73
+ let self_total = size_hint:: pow_scalar_base ( 2 , src_total) ;
74
+
75
+ if self . pos < usize:: MAX {
76
+ // Subtract count of elements already yielded from total.
77
+ size_hint:: sub_scalar ( self_total, self . pos )
78
+ } else {
79
+ // Fallback: self.pos is saturated and no longer reliable.
80
+ ( 0 , self_total. 1 )
81
+ }
82
+ }
56
83
}
0 commit comments