@@ -909,15 +909,19 @@ fn combinations_zero() {
909909 it:: assert_equal ( ( 0 ..0 ) . combinations ( 0 ) , vec ! [ vec![ ] ] ) ;
910910}
911911
912+ fn binomial ( n : usize , k : usize ) -> usize {
913+ if k > n {
914+ 0
915+ } else {
916+ ( n - k + 1 ..=n) . product :: < usize > ( ) / ( 1 ..=k) . product :: < usize > ( )
917+ }
918+ }
919+
912920#[ test]
913921fn combinations_range_count ( ) {
914922 for n in 0 ..=10 {
915923 for k in 0 ..=10 {
916- let len = if k<=n {
917- ( n - k + 1 ..=n) . product :: < usize > ( ) / ( 1 ..=k) . product :: < usize > ( )
918- } else {
919- 0
920- } ;
924+ let len = binomial ( n, k) ;
921925 let mut it = ( 0 ..n) . combinations ( k) ;
922926 assert_eq ! ( len, it. clone( ) . count( ) ) ;
923927 assert_eq ! ( len, it. size_hint( ) . 0 ) ;
@@ -935,6 +939,47 @@ fn combinations_range_count() {
935939 }
936940}
937941
942+ #[ test]
943+ fn combinations_inexact_size_hints ( ) {
944+ for k in 0 ..=10 {
945+ let mut numbers = ( 0 ..18 ) . filter ( |i| i % 2 == 0 ) ; // 9 elements
946+ let mut it = numbers. clone ( ) . combinations ( k) ;
947+ let real_n = numbers. clone ( ) . count ( ) ;
948+ let len = binomial ( real_n, k) ;
949+ assert_eq ! ( len, it. clone( ) . count( ) ) ;
950+
951+ let mut nb_loaded = numbers. by_ref ( ) . take ( k) . count ( ) ; // because of `LazyBuffer::prefill(k)`
952+ let sh = numbers. size_hint ( ) ;
953+ assert_eq ! ( binomial( sh. 0 + nb_loaded, k) , it. size_hint( ) . 0 ) ;
954+ assert_eq ! ( sh. 1 . map( |n| binomial( n + nb_loaded, k) ) , it. size_hint( ) . 1 ) ;
955+
956+ for next_count in 1 ..=len {
957+ let elem = it. next ( ) ;
958+ assert ! ( elem. is_some( ) ) ;
959+ assert_eq ! ( len - next_count, it. clone( ) . count( ) ) ;
960+ // It does not load anything more the very first time (it's prefilled).
961+ if next_count > 1 {
962+ // Then it loads one item each time until exhausted.
963+ let nb = numbers. next ( ) ;
964+ if nb. is_some ( ) {
965+ nb_loaded += 1 ;
966+ }
967+ }
968+ let sh = numbers. size_hint ( ) ;
969+ if next_count > real_n - k + 1 {
970+ assert_eq ! ( 0 , sh. 0 ) ;
971+ assert_eq ! ( Some ( 0 ) , sh. 1 ) ;
972+ assert_eq ! ( real_n, nb_loaded) ;
973+ // Once it's fully loaded, size hints of `it` are exacts.
974+ }
975+ assert_eq ! ( binomial( sh. 0 + nb_loaded, k) - next_count, it. size_hint( ) . 0 ) ;
976+ assert_eq ! ( sh. 1 . map( |n| binomial( n + nb_loaded, k) - next_count) , it. size_hint( ) . 1 ) ;
977+ }
978+ let should_be_none = it. next ( ) ;
979+ assert ! ( should_be_none. is_none( ) ) ;
980+ }
981+ }
982+
938983#[ test]
939984fn permutations_zero ( ) {
940985 it:: assert_equal ( ( 1 ..3 ) . permutations ( 0 ) , vec ! [ vec![ ] ] ) ;
@@ -989,6 +1034,23 @@ fn powerset() {
9891034 assert_eq ! ( ( 0 ..4 ) . powerset( ) . count( ) , 1 << 4 ) ;
9901035 assert_eq ! ( ( 0 ..8 ) . powerset( ) . count( ) , 1 << 8 ) ;
9911036 assert_eq ! ( ( 0 ..16 ) . powerset( ) . count( ) , 1 << 16 ) ;
1037+
1038+ for n in 0 ..=10 {
1039+ let mut it = ( 0 ..n) . powerset ( ) ;
1040+ let len = 2_usize . pow ( n) ;
1041+ assert_eq ! ( len, it. clone( ) . count( ) ) ;
1042+ assert_eq ! ( len, it. size_hint( ) . 0 ) ;
1043+ assert_eq ! ( Some ( len) , it. size_hint( ) . 1 ) ;
1044+ for count in ( 0 ..len) . rev ( ) {
1045+ let elem = it. next ( ) ;
1046+ assert ! ( elem. is_some( ) ) ;
1047+ assert_eq ! ( count, it. clone( ) . count( ) ) ;
1048+ assert_eq ! ( count, it. size_hint( ) . 0 ) ;
1049+ assert_eq ! ( Some ( count) , it. size_hint( ) . 1 ) ;
1050+ }
1051+ let should_be_none = it. next ( ) ;
1052+ assert ! ( should_be_none. is_none( ) ) ;
1053+ }
9921054}
9931055
9941056#[ test]
0 commit comments