|
1 | | -use super::traits::MutableSorter; |
2 | 1 | use crate::math::PCG32; |
| 2 | +use crate::sorting::traits::Sorter; |
3 | 3 | use std::time::{SystemTime, UNIX_EPOCH}; |
4 | 4 |
|
5 | | -const DEFAULT: u64 = 4294967296; |
| 5 | +const DEFAULT: u64 = 2 << 31; // 2^32 |
6 | 6 |
|
7 | | -pub struct BogoSort; |
| 7 | +fn is_sorted<T: Ord>(arr: &[T], len: usize) -> bool { |
| 8 | + if len <= 1 { |
| 9 | + return true; |
| 10 | + } |
8 | 11 |
|
9 | | -impl BogoSort { |
10 | | - fn is_sorted<T: Ord>(arr: &[T], len: usize) -> bool { |
11 | | - for i in 0..len - 1 { |
12 | | - if arr[i] > arr[i + 1] { |
13 | | - return false; |
14 | | - } |
| 12 | + for i in 0..len - 1 { |
| 13 | + if arr[i] > arr[i + 1] { |
| 14 | + return false; |
15 | 15 | } |
16 | | - |
17 | | - true |
18 | | - } |
19 | | - #[cfg(target_pointer_width = "64")] |
20 | | - fn generate_index(range: usize, generator: &mut PCG32) -> usize { |
21 | | - generator.get_u64() as usize % range |
22 | 16 | } |
23 | 17 |
|
24 | | - #[cfg(not(target_pointer_width = "64"))] |
25 | | - fn generate_index(range: usize, generator: &mut PCG32) -> usize { |
26 | | - generator.get_u32() as usize % range |
| 18 | + true |
| 19 | +} |
| 20 | +#[cfg(target_pointer_width = "64")] |
| 21 | +fn generate_index(range: usize, generator: &mut PCG32) -> usize { |
| 22 | + generator.get_u64() as usize % range |
| 23 | +} |
| 24 | + |
| 25 | +#[cfg(not(target_pointer_width = "64"))] |
| 26 | +fn generate_index(range: usize, generator: &mut PCG32) -> usize { |
| 27 | + generator.get_u32() as usize % range |
| 28 | +} |
| 29 | + |
| 30 | +/** |
| 31 | + * Fisher–Yates shuffle for generating random permutation. |
| 32 | + */ |
| 33 | +fn permute_randomly<T>(arr: &mut [T], len: usize, generator: &mut PCG32) { |
| 34 | + if len <= 1 { |
| 35 | + return; |
27 | 36 | } |
28 | 37 |
|
29 | | - /** |
30 | | - * Fisher–Yates shuffle for generating random permutation. |
31 | | - */ |
32 | | - fn permute_randomly<T>(arr: &mut [T], len: usize, generator: &mut PCG32) { |
33 | | - for i in (1..len).rev() { |
34 | | - let j = BogoSort::generate_index(i + 1, generator); |
35 | | - arr.swap(i, j); |
36 | | - } |
| 38 | + for i in (1..len).rev() { |
| 39 | + let j = generate_index(i + 1, generator); |
| 40 | + arr.swap(i, j); |
37 | 41 | } |
38 | 42 | } |
39 | 43 |
|
40 | | -impl<T> MutableSorter<T> for BogoSort { |
41 | | - fn sort(arr: &mut [T]) |
42 | | - where |
43 | | - T: Ord, |
44 | | - { |
45 | | - let seed = match SystemTime::now().duration_since(UNIX_EPOCH) { |
46 | | - Ok(duration) => duration.as_millis() as u64, |
47 | | - Err(_) => DEFAULT, |
48 | | - }; |
| 44 | +fn bogo_sort<T: Ord>(arr: &mut [T]) { |
| 45 | + let seed = match SystemTime::now().duration_since(UNIX_EPOCH) { |
| 46 | + Ok(duration) => duration.as_millis() as u64, |
| 47 | + Err(_) => DEFAULT, |
| 48 | + }; |
49 | 49 |
|
50 | | - let mut random_generator = PCG32::new_default(seed); |
| 50 | + let mut random_generator = PCG32::new_default(seed); |
51 | 51 |
|
52 | | - let arr_length = arr.len(); |
53 | | - while !BogoSort::is_sorted(arr, arr_length) { |
54 | | - BogoSort::permute_randomly(arr, arr_length, &mut random_generator); |
55 | | - } |
| 52 | + let arr_length = arr.len(); |
| 53 | + while !is_sorted(arr, arr_length) { |
| 54 | + permute_randomly(arr, arr_length, &mut random_generator); |
| 55 | + } |
| 56 | +} |
| 57 | + |
| 58 | +pub struct BogoSort; |
| 59 | + |
| 60 | +impl<T> Sorter<T> for BogoSort |
| 61 | +where |
| 62 | + T: Ord + Copy, |
| 63 | +{ |
| 64 | + fn sort_inplace(arr: &mut [T]) { |
| 65 | + bogo_sort(arr); |
56 | 66 | } |
57 | 67 | } |
58 | 68 |
|
59 | 69 | #[cfg(test)] |
60 | 70 | mod tests { |
61 | | - use super::super::traits::MutableSorter; |
62 | | - use super::BogoSort; |
| 71 | + use crate::sorting::traits::Sorter; |
| 72 | + use crate::sorting::BogoSort; |
63 | 73 |
|
64 | | - sorting_tests!(BogoSort::sort, inplace); |
| 74 | + sorting_tests!(BogoSort::sort, bogo_sort); |
| 75 | + sorting_tests!(BogoSort::sort_inplace, bogo_sort, inplace); |
65 | 76 | } |
0 commit comments