1
+ /// Based on https://stackoverflow.com/a/30898130/4322240.
2
+
3
+ /// Representation of a state in which the iterator can be.
4
+ /// elements: contains the elements to be partitioned. All elements are treated
5
+ /// as distinct.
6
+ /// index_map: in terms of the linked post, index_map[i] = p_i (but 0-indexed)
7
+ /// is the partition class to which elements[i] belongs in the current
8
+ /// partition
9
+ /// initialized: marks if the Partition element was just initialized and hence
10
+ /// was not generated by next()
11
+ pub struct Partition < ' a , T > where T : Copy {
12
+ elements : & ' a Vec < T > ,
13
+ index_map : Vec < usize > ,
14
+ initialized : bool ,
15
+ }
16
+
17
+ type PartitionRepresentation < T > = Vec < Vec < T > > ;
18
+
19
+
20
+ impl < ' a , T > Partition < ' a , T > where T : Copy {
21
+ // extracts the current partition of the iterator
22
+ fn create_partition ( & self ) -> PartitionRepresentation < T > {
23
+ // max_index is the highest number used for a class in the partition.
24
+ // Since the first class is numbered 0, there are max_index + 1 different classes.
25
+ if let Some ( & max_index) = self . index_map . iter ( ) . max ( ) {
26
+ // initialize Vec's for the classes
27
+ let mut partition_classes = vec ! [ Vec :: new( ) ; max_index + 1 ] ;
28
+ for i in 0 ..self . index_map . len ( ) {
29
+ // elements[i] belongs to the partition class index_map[i]
30
+ partition_classes[ self . index_map [ i] ] . push ( self . elements [ i] ) ;
31
+ }
32
+ return partition_classes;
33
+ } else {
34
+ // The index_map might have length 0, which means that there are no elements.
35
+ // There is precisely one partition of the empty set, namely the partition with no classes.
36
+ return Vec :: new ( ) ;
37
+ }
38
+ }
39
+ }
40
+ impl < ' a , T > Iterator for Partition < ' a , T > where T : Copy {
41
+ type Item = PartitionRepresentation < T > ;
42
+
43
+ fn next ( & mut self ) -> Option < Self :: Item > {
44
+ if self . initialized {
45
+ self . initialized = false ;
46
+ return Some ( self . create_partition ( ) ) ;
47
+ }
48
+ // search for the highest index at which the index_map is incrementable (see the linked post)
49
+ for index in ( 1 ..self . index_map . len ( ) ) . rev ( ) {
50
+ if ( 0 ..index) . any ( |x| self . index_map [ x] == self . index_map [ index] ) {
51
+ // increment the incrementable index
52
+ self . index_map [ index] += 1 ;
53
+ // set all following entries to the lexicographically smallest suffix that makes the
54
+ // index_map viable (see linked post), i.e. to zero.
55
+ for x in index + 1 ..self . index_map . len ( ) {
56
+ self . index_map [ x] = 0 ;
57
+ }
58
+ return Some ( self . create_partition ( ) ) ;
59
+ }
60
+ }
61
+ // if there is no incrementable index, we have enumerated the last possible partition.
62
+ return None ;
63
+ }
64
+ }
65
+ /// Returns an Iterator over all partitions of the given Vec.
66
+ /// Example usage:
67
+ /// ```
68
+ /// for partition in partitions(&vec![7,8,9]){
69
+ /// println!("{:?}", partition);
70
+ /// }
71
+ /// ```
72
+ pub fn partitions < ' a , T > ( v : & ' a Vec < T > ) -> Partition < ' a , T > where T : Copy {
73
+ Partition :: < T > { elements : v, index_map : vec ! [ 0 ; v. len( ) ] , initialized : true }
74
+ }
0 commit comments