use rand::prelude::*;
pub trait RandomSelector: Send + Sync {
fn select_index(&mut self, len: usize) -> Option<usize>;
fn shuffle_usize(&mut self, items: &mut [usize]);
}
pub struct DefaultRandomSelector {
rng: StdRng,
}
impl DefaultRandomSelector {
pub fn new() -> Self {
Self {
rng: StdRng::from_seed(rand::rng().random()),
}
}
pub fn with_seed(seed: u64) -> Self {
Self {
rng: StdRng::seed_from_u64(seed),
}
}
pub fn select<'a, T>(&mut self, items: &'a [T]) -> Option<&'a T> {
items.choose(&mut self.rng)
}
pub fn shuffle<T>(&mut self, items: &mut [T]) {
items.shuffle(&mut self.rng);
}
}
impl Default for DefaultRandomSelector {
fn default() -> Self {
Self::new()
}
}
impl RandomSelector for DefaultRandomSelector {
fn select_index(&mut self, len: usize) -> Option<usize> {
if len == 0 {
None
} else {
Some(self.rng.random_range(0..len))
}
}
fn shuffle_usize(&mut self, items: &mut [usize]) {
items.shuffle(&mut self.rng);
}
}
pub struct MockRandomSelector {
sequence: Vec<usize>, index: usize, }
impl MockRandomSelector {
pub fn new(sequence: Vec<usize>) -> Self {
Self { sequence, index: 0 }
}
}
impl RandomSelector for MockRandomSelector {
fn select_index(&mut self, len: usize) -> Option<usize> {
if len == 0 || self.sequence.is_empty() {
return None;
}
let idx = self.sequence[self.index % self.sequence.len()] % len;
self.index += 1;
Some(idx)
}
fn shuffle_usize(&mut self, _items: &mut [usize]) {
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_selector() {
let mut selector = DefaultRandomSelector::with_seed(42);
let items = vec![1, 2, 3, 4, 5];
let result = selector.select(&items);
assert!(result.is_some());
assert!(items.contains(result.unwrap()));
}
#[test]
fn test_default_selector_empty() {
let mut selector = DefaultRandomSelector::new();
let items: Vec<i32> = vec![];
let result = selector.select(&items);
assert!(result.is_none());
}
#[test]
fn test_mock_selector() {
let mut selector = MockRandomSelector::new(vec![0, 2, 1]);
assert_eq!(selector.select_index(3), Some(0)); assert_eq!(selector.select_index(3), Some(2)); assert_eq!(selector.select_index(3), Some(1)); assert_eq!(selector.select_index(3), Some(0)); }
#[test]
fn test_mock_selector_empty() {
let mut selector = MockRandomSelector::new(vec![0]);
assert_eq!(selector.select_index(0), None);
}
#[test]
fn test_shuffle() {
let mut selector = DefaultRandomSelector::with_seed(42);
let mut items = vec![1, 2, 3, 4, 5];
let original = items.clone();
selector.shuffle(&mut items);
items.sort();
assert_eq!(items, original);
}
}