sorting_race/services/
generator.rs

1//! Deterministic array generation for sorting race
2
3use crate::models::config::Distribution;
4use rand::{Rng, SeedableRng};
5use rand::rngs::StdRng;
6
7/// Deterministic array generator using seeded RNG
8#[derive(Debug)]
9pub struct ArrayGenerator {
10    seed: u64,
11}
12
13impl ArrayGenerator {
14    /// Create a new array generator with specified seed
15    pub fn new(seed: u64) -> Self {
16        Self { seed }
17    }
18
19    /// Generate an array with the specified distribution
20    pub fn generate(&self, size: usize, distribution: &Distribution) -> Vec<i32> {
21        if size == 0 {
22            return Vec::new();
23        }
24
25        match distribution {
26            Distribution::Shuffled => self.generate_shuffled(size),
27            Distribution::NearlySorted => self.generate_nearly_sorted(size),
28            Distribution::Reversed => self.generate_reversed(size),
29            Distribution::FewUnique => self.generate_few_unique(size),
30            Distribution::Sorted => self.generate_sorted(size),
31            Distribution::WithDuplicates => self.generate_with_duplicates(size),
32        }
33    }
34
35    /// Generate a random shuffled array
36    fn generate_shuffled(&self, size: usize) -> Vec<i32> {
37        let mut rng = StdRng::seed_from_u64(self.seed);
38        let mut array: Vec<i32> = (1..=size as i32).collect();
39        
40        // Fisher-Yates shuffle
41        for i in (1..size).rev() {
42            let j = rng.random_range(0..=i);
43            array.swap(i, j);
44        }
45        
46        array
47    }
48
49    /// Generate a nearly sorted array (90% sorted, 10% out of place)
50    fn generate_nearly_sorted(&self, size: usize) -> Vec<i32> {
51        let mut rng = StdRng::seed_from_u64(self.seed);
52        let mut array: Vec<i32> = (1..=size as i32).collect();
53        
54        // Randomly swap ~10% of elements
55        let swaps = (size / 10).max(1);
56        for _ in 0..swaps {
57            let i = rng.random_range(0..size);
58            let j = rng.random_range(0..size);
59            array.swap(i, j);
60        }
61        
62        array
63    }
64
65    /// Generate a reverse sorted array
66    fn generate_reversed(&self, size: usize) -> Vec<i32> {
67        (1..=size as i32).rev().collect()
68    }
69
70    /// Generate an array with few unique values
71    fn generate_few_unique(&self, size: usize) -> Vec<i32> {
72        let mut rng = StdRng::seed_from_u64(self.seed);
73        let unique_count = (size / 10).max(3).min(size); // ~10% unique values
74        let values: Vec<i32> = (1..=unique_count as i32).collect();
75        
76        let mut array = Vec::with_capacity(size);
77        for _ in 0..size {
78            let idx = rng.random_range(0..values.len());
79            array.push(values[idx]);
80        }
81        
82        array
83    }
84
85    /// Generate a pre-sorted array
86    fn generate_sorted(&self, size: usize) -> Vec<i32> {
87        (1..=size as i32).collect()
88    }
89
90    /// Generate an array with many duplicates
91    fn generate_with_duplicates(&self, size: usize) -> Vec<i32> {
92        let mut rng = StdRng::seed_from_u64(self.seed);
93        let mut array = Vec::with_capacity(size);
94        
95        // Generate with 50% duplicates
96        for i in 0..size {
97            if i < size / 2 {
98                // First half: sequential values
99                array.push((i + 1) as i32);
100            } else {
101                // Second half: random duplicates from first half
102                let idx = rng.random_range(0..size / 2);
103                array.push((idx + 1) as i32);
104            }
105        }
106        
107        // Shuffle the array
108        for i in (1..size).rev() {
109            let j = rng.random_range(0..=i);
110            array.swap(i, j);
111        }
112        
113        array
114    }
115
116    /// Validate that the generated array is correct
117    pub fn validate_array(array: &[i32], size: usize, distribution: &Distribution) -> bool {
118        if array.len() != size {
119            return false;
120        }
121
122        if size == 0 {
123            return true;
124        }
125
126        match distribution {
127            Distribution::Sorted => {
128                // Check if array is sorted
129                array.windows(2).all(|w| w[0] <= w[1])
130            }
131            Distribution::Reversed => {
132                // Check if array is reverse sorted
133                array.windows(2).all(|w| w[0] >= w[1])
134            }
135            _ => {
136                // For other distributions, just check that values are reasonable
137                array.iter().all(|&x| x > 0 && x <= size as i32 * 2)
138            }
139        }
140    }
141}
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146
147    #[test]
148    fn test_deterministic_generation() {
149        let gen1 = ArrayGenerator::new(42);
150        let gen2 = ArrayGenerator::new(42);
151        
152        let array1 = gen1.generate(10, &Distribution::Shuffled);
153        let array2 = gen2.generate(10, &Distribution::Shuffled);
154        
155        assert_eq!(array1, array2);
156    }
157
158    #[test]
159    fn test_different_seeds() {
160        let gen1 = ArrayGenerator::new(42);
161        let gen2 = ArrayGenerator::new(43);
162        
163        let array1 = gen1.generate(10, &Distribution::Shuffled);
164        let array2 = gen2.generate(10, &Distribution::Shuffled);
165        
166        assert_ne!(array1, array2);
167    }
168
169    #[test]
170    fn test_sorted_distribution() {
171        let generator = ArrayGenerator::new(42);
172        let array = generator.generate(10, &Distribution::Sorted);
173        
174        assert_eq!(array, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
175    }
176
177    #[test]
178    fn test_reversed_distribution() {
179        let generator = ArrayGenerator::new(42);
180        let array = generator.generate(10, &Distribution::Reversed);
181        
182        assert_eq!(array, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1]);
183    }
184
185    #[test]
186    fn test_empty_array() {
187        let generator = ArrayGenerator::new(42);
188        let array = generator.generate(0, &Distribution::Shuffled);
189        
190        assert!(array.is_empty());
191    }
192
193    #[test]
194    fn test_array_validation() {
195        let generator = ArrayGenerator::new(42);
196        
197        let sorted = generator.generate(5, &Distribution::Sorted);
198        assert!(ArrayGenerator::validate_array(&sorted, 5, &Distribution::Sorted));
199        
200        let reversed = generator.generate(5, &Distribution::Reversed);
201        assert!(ArrayGenerator::validate_array(&reversed, 5, &Distribution::Reversed));
202        
203        let shuffled = generator.generate(5, &Distribution::Shuffled);
204        assert!(ArrayGenerator::validate_array(&shuffled, 5, &Distribution::Shuffled));
205    }
206}