ep_core/
random_permutation.rs1use crate::RandomNumberGenerator;
20use sp_runtime::traits::Hash;
21
22#[cfg(not(feature = "std"))]
23use sp_std::vec::Vec;
24
25pub trait RandomPermutation {
28 type Item;
29
30 fn random_permutation<Hashing: Hash>(
33 self,
34 random: &mut RandomNumberGenerator<Hashing>,
35 ) -> Option<Vec<Self::Item>>;
36}
37
38impl<T> RandomPermutation for Vec<T> {
39 type Item = T;
40
41 fn random_permutation<Hashing: Hash>(
42 self,
43 random: &mut RandomNumberGenerator<Hashing>,
44 ) -> Option<Vec<T>> {
45 let mut input = self;
48
49 if input.is_empty() {
50 None
51 } else {
52 let size = input.len();
53 let mut r = Vec::with_capacity(size);
54
55 for i in 1..=size {
56 r.push(input.swap_remove(random.pick_usize(size - i)));
58 }
59 Some(r)
60 }
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use sp_runtime::traits::BlakeTwo256;
68
69 #[test]
70 fn random_permutation_works() {
71 let mut random_source =
72 RandomNumberGenerator::<BlakeTwo256>::new(BlakeTwo256::hash(b"my_seed"));
73 let mut random_source_2 =
74 RandomNumberGenerator::<BlakeTwo256>::new(BlakeTwo256::hash(b"my_seed2"));
75 let input = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
76
77 assert_eq!(
78 input.clone().random_permutation(&mut random_source),
79 Some(vec![5, 9, 7, 4, 6, 8, 2, 3, 1, 10])
80 );
81
82 assert_eq!(
84 input.clone().random_permutation(&mut random_source),
85 Some(vec![9, 8, 3, 5, 6, 2, 10, 4, 7, 1])
86 );
87
88 assert_eq!(
90 input.random_permutation(&mut random_source_2),
91 Some(vec![1, 7, 8, 9, 2, 3, 10, 5, 4, 6])
92 );
93
94 assert_eq!(Vec::<u8>::new().random_permutation(&mut random_source_2), None)
95 }
96}