@@ -132,13 +132,17 @@ pub trait SliceRandom {
132
132
133
133
/// Extension trait on iterators, providing random sampling methods.
134
134
pub trait IteratorRandom : Iterator + Sized {
135
- /// Choose one element at random from the iterator.
135
+ /// Choose one element at random from the iterator. If you have a slice,
136
+ /// it's significantly faster to call the [`choose`] or [`choose_mut`]
137
+ /// functions using the slice instead.
136
138
///
137
139
/// Returns `None` if and only if the iterator is empty.
138
140
///
139
141
/// Complexity is `O(n)`, where `n` is the length of the iterator.
140
142
/// This likely consumes multiple random numbers, but the exact number
141
143
/// is unspecified.
144
+ /// [`choose`]: trait.SliceRandom.html#method.choose
145
+ /// [`choose_mut`]: trait.SliceRandom.html#method.choose_mut
142
146
fn choose < R > ( mut self , rng : & mut R ) -> Option < Self :: Item >
143
147
where R : Rng + ?Sized
144
148
{
@@ -518,19 +522,47 @@ mod test {
518
522
use alloc:: Vec ;
519
523
520
524
#[ test]
521
- fn test_choose ( ) {
525
+ fn test_slice_choose ( ) {
522
526
let mut r = :: test:: rng ( 107 ) ;
523
- assert_eq ! ( [ 1 , 1 , 1 ] . choose( & mut r) , Some ( & 1 ) ) ;
524
-
525
- let mut v = [ 2 ] ;
526
- v. choose_mut ( & mut r) . map ( |x| * x = 5 ) ;
527
- assert_eq ! ( v[ 0 ] , 5 ) ;
527
+ let chars = [ 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' ] ;
528
+ let mut chosen = [ 0i32 ; 14 ] ;
529
+ for _ in 0 ..1000 {
530
+ let picked = * chars. choose ( & mut r) . unwrap ( ) ;
531
+ chosen[ ( picked as usize ) - ( 'a' as usize ) ] += 1 ;
532
+ }
533
+ for count in chosen. iter ( ) {
534
+ let err = * count - ( 1000 / ( chars. len ( ) as i32 ) ) ;
535
+ assert ! ( -20 <= err && err <= 20 ) ;
536
+ }
528
537
529
- let v = [ 3 , 3 , 3 , 3 ] ;
530
- assert_eq ! ( v. iter( ) . choose( & mut r) , Some ( & 3 ) ) ;
538
+ chosen. iter_mut ( ) . for_each ( |x| * x = 0 ) ;
539
+ for _ in 0 ..1000 {
540
+ * chosen. choose_mut ( & mut r) . unwrap ( ) += 1 ;
541
+ }
542
+ for count in chosen. iter ( ) {
543
+ let err = * count - ( 1000 / ( chosen. len ( ) as i32 ) ) ;
544
+ assert ! ( -20 <= err && err <= 20 ) ;
545
+ }
531
546
532
- let v: & [ isize ] = & [ ] ;
547
+ let mut v: [ isize ; 0 ] = [ ] ;
533
548
assert_eq ! ( v. choose( & mut r) , None ) ;
549
+ assert_eq ! ( v. choose_mut( & mut r) , None ) ;
550
+ }
551
+
552
+ #[ test]
553
+ fn test_iterator_choose ( ) {
554
+ let mut r = :: test:: rng ( 109 ) ;
555
+ let mut chosen = [ 0i32 ; 9 ] ;
556
+ for _ in 0 ..1000 {
557
+ let picked = ( 0 ..9 ) . choose ( & mut r) . unwrap ( ) ;
558
+ chosen[ picked] += 1 ;
559
+ }
560
+ for count in chosen. iter ( ) {
561
+ let err = * count - 1000 / 9 ;
562
+ assert ! ( -25 <= err && err <= 25 ) ;
563
+ }
564
+
565
+ assert_eq ! ( ( 0 ..0 ) . choose( & mut r) , None ) ;
534
566
}
535
567
536
568
#[ test]
@@ -547,10 +579,29 @@ mod test {
547
579
two. shuffle ( & mut r) ;
548
580
assert ! ( two == [ 1 , 2 ] || two == [ 2 , 1 ] ) ;
549
581
550
- let mut x = [ 1 , 1 , 1 ] ;
551
- x. shuffle ( & mut r) ;
552
- let b: & [ _ ] = & [ 1 , 1 , 1 ] ;
553
- assert_eq ! ( x, b) ;
582
+ let mut counts = [ 0i32 ; 24 ] ;
583
+ for _ in 0 ..10000 {
584
+ let mut arr: [ usize ; 4 ] = [ 0 , 1 , 2 , 3 ] ;
585
+ arr. shuffle ( & mut r) ;
586
+ let mut permutation = 0usize ;
587
+ let mut pos_value = counts. len ( ) ;
588
+ for i in 0 ..4 {
589
+ pos_value /= 4 - i;
590
+ let pos = arr. iter ( ) . position ( |& x| x == i) . unwrap ( ) ;
591
+ assert ! ( pos < ( 4 - i) ) ;
592
+ permutation += pos * pos_value;
593
+ arr[ pos..] . rotate_left ( 1 ) ;
594
+ assert_eq ! ( arr[ 3 ] , i) ;
595
+ }
596
+ for i in 0 ..4 {
597
+ assert_eq ! ( arr[ i] , i) ;
598
+ }
599
+ counts[ permutation] += 1 ;
600
+ }
601
+ for count in counts. iter ( ) {
602
+ let err = * count - 10000i32 / 24 ;
603
+ assert ! ( -50 <= err && err <= 50 ) ;
604
+ }
554
605
}
555
606
556
607
#[ test]
0 commit comments