@@ -909,15 +909,19 @@ fn combinations_zero() {
909
909
it:: assert_equal ( ( 0 ..0 ) . combinations ( 0 ) , vec ! [ vec![ ] ] ) ;
910
910
}
911
911
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
+
912
920
#[ test]
913
921
fn combinations_range_count ( ) {
914
922
for n in 0 ..=10 {
915
923
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) ;
921
925
let mut it = ( 0 ..n) . combinations ( k) ;
922
926
assert_eq ! ( len, it. clone( ) . count( ) ) ;
923
927
assert_eq ! ( len, it. size_hint( ) . 0 ) ;
@@ -935,6 +939,47 @@ fn combinations_range_count() {
935
939
}
936
940
}
937
941
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
+
938
983
#[ test]
939
984
fn permutations_zero ( ) {
940
985
it:: assert_equal ( ( 1 ..3 ) . permutations ( 0 ) , vec ! [ vec![ ] ] ) ;
0 commit comments