-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathexercise_5_1_2.rs
More file actions
64 lines (51 loc) · 1.4 KB
/
Copy pathexercise_5_1_2.rs
File metadata and controls
64 lines (51 loc) · 1.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use rand::Rng;
#[allow(clippy::cast_possible_truncation)] // Expected.
#[must_use]
pub fn random(a: i32, b: i32) -> i32 {
let range = b - a;
let bits_needed = f64::from(b - a + 1).log2().ceil() as _;
let mut rng = rand::thread_rng();
loop {
let mut result = 0;
for _ in 0..bits_needed {
result <<= 1;
result |= i32::from(rng.gen::<bool>());
}
if result <= range {
return a + result;
}
}
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
const _TEST_RANGE: i32 = 16;
const _TEST_SAMPLES: i32 = 1000;
#[test]
fn test_random_range() {
for start in -_TEST_RANGE..=_TEST_RANGE {
for end in start..=_TEST_RANGE {
for _ in 0.._TEST_SAMPLES {
let r = super::random(start, end);
assert!(r >= start);
assert!(r <= end);
}
}
}
}
#[test]
fn test_random_coverage() {
let mut set = HashSet::new();
for start in -_TEST_RANGE..=_TEST_RANGE {
for end in start..=_TEST_RANGE {
set.extend(start..=end);
loop {
set.remove(&super::random(start, end));
if set.is_empty() {
break;
}
}
}
}
}
}