jabba_lib/
jrandom.rs

1//! random
2
3use rand::seq::SliceRandom;
4use rand::Rng;
5
6/// Returns a random i32 from range `[lo, hi)`, where `lo` is included
7/// and `hi` is excluded.
8///
9/// Similar to Python's `random.randrange()`.
10///
11/// # Examples
12///
13/// ```
14/// let number = jabba_lib::jrandom::randrange(1, 6);
15///
16/// assert!(1 <= number && number < 6);
17/// ```
18pub fn randrange(lo: i32, hi: i32) -> i32 {
19    rand::thread_rng().gen_range(lo..hi)
20}
21
22/// Returns a random i32 from range `[lo, hi]`, where both `lo` and `hi` are included.
23///
24/// Similar to Python's `random.randint()`.
25///
26/// # Examples
27///
28/// ```
29/// let number = jabba_lib::jrandom::randint(1, 6);
30///
31/// assert!(1 <= number && number <= 6);
32/// ```
33pub fn randint(lo: i32, hi: i32) -> i32 {
34    rand::thread_rng().gen_range(lo..=hi)
35}
36
37/// Shuffles a vector / array in place.
38///
39/// Similar to Python's `random.shuffle()`.
40///
41/// # Examples
42///
43/// ```
44/// let mut numbers = vec![1, 2, 3, 4, 5];
45/// jabba_lib::jrandom::shuffle(&mut numbers);
46/// // now the elements in `numbers` are shuffled
47/// // `numbers` could be [4, 2, 3, 1, 5], for instance
48/// ```
49pub fn shuffle<T>(v: &mut [T]) {
50    let mut rng = rand::thread_rng();
51
52    v.shuffle(&mut rng);
53}
54
55/// Returns an `f64` from the interval `[0.0, 1.0)`.
56///
57/// Similar to Python's `random.random()`.
58///
59/// # Examples
60///
61/// ```
62/// let number = jabba_lib::jrandom::random();
63/// // now 0.0 <= number < 1.0
64/// ```
65pub fn random() -> f64 {
66    let mut rng = rand::thread_rng();
67
68    rng.gen::<f64>()
69}
70
71/// Chooses a random element from an array / vector.
72///
73/// Returns `None` if the array / vector is empty.
74///
75/// # Examples
76///
77/// ```
78/// let v = vec![1, 2, 3];
79/// let elem: &i32 = jabba_lib::jrandom::choice(&v).unwrap();
80/// // elem is now 1 or 2 or 3
81/// ```
82pub fn choice<T>(v: &[T]) -> Option<&T> {
83    if v.is_empty() {
84        return None;
85    }
86    // else
87    let idx = randrange(0, v.len() as i32) as usize;
88    Some(&v[idx])
89}
90
91// ==========================================================================
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn randrange_test1() {
99        for _ in 0..10 {
100            let value = randrange(1, 2);
101            assert!(value == 1);
102        }
103        //
104        for _ in 0..10 {
105            let value = randrange(1, 3);
106            assert!(value == 1 || value == 2);
107        }
108        //
109        for _ in 0..1000 {
110            let value = randrange(1, 10);
111            assert!(value >= 1 && value < 10);
112        }
113    }
114
115    #[test]
116    fn randint_test1() {
117        for _ in 0..10 {
118            let value = randint(1, 1);
119            assert!(value == 1);
120        }
121        //
122        for _ in 0..10 {
123            let value = randint(1, 2);
124            assert!(value >= 1 && value <= 2);
125        }
126        //
127        for _ in 0..1000 {
128            let value = randint(1, 10);
129            assert!(value >= 1 && value <= 10);
130        }
131    }
132
133    #[test]
134    fn randrange_test2() {
135        let mut v = vec![];
136        for _ in 0..1000 {
137            let value = randrange(1, 10);
138            v.push(value);
139        }
140        v.sort();
141        v.dedup();
142        for i in 1..=9 {
143            assert!(v.contains(&i));
144        }
145        assert_eq!(v.contains(&0), false);
146        assert_eq!(v.contains(&10), false);
147        //
148        assert!(v[0] == 1);
149        assert!(v[v.len() - 1] == 9);
150    }
151
152    #[test]
153    fn randint_test2() {
154        let mut v = vec![];
155        for _ in 0..1000 {
156            let value = randint(1, 10);
157            v.push(value);
158        }
159        v.sort();
160        v.dedup();
161        for i in 1..=10 {
162            assert!(v.contains(&i));
163        }
164        assert_eq!(v.contains(&0), false);
165        assert_eq!(v.contains(&11), false);
166        //
167        assert!(v[0] == 1);
168        assert!(v[v.len() - 1] == 10);
169    }
170
171    #[test]
172    fn shuffle_test1() {
173        let mut v = vec![];
174        for i in 1..=100 {
175            v.push(i);
176        }
177        assert!(v.len() == 100);
178        let backup = v.clone();
179        //
180        shuffle(&mut v);
181        assert!(v.len() == backup.len());
182        assert!(v != backup);
183        v.sort();
184        assert!(v == backup);
185    }
186
187    #[test]
188    fn random_test1() {
189        for _ in 0..100 {
190            let number = random();
191            assert!(number >= 0.0 && number < 1.0)
192        }
193    }
194
195    #[test]
196    fn choice_test1() {
197        let v = vec![1, 2, 3];
198        for _ in 0..100 {
199            let &elem = choice(&v).unwrap();
200            assert!(v.contains(&elem));
201        }
202    }
203
204    #[test]
205    fn choice_test2() {
206        let empty = Vec::<i32>::new();
207        let elem = choice(&empty);
208        assert_eq!(elem, None);
209    }
210}