From 04902578ccf58d63f842d06dac9d7d0ad7a971c4 Mon Sep 17 00:00:00 2001 From: Victor Moisa Date: Sun, 21 Jan 2024 00:32:30 +0200 Subject: [PATCH 1/6] Added Bogobogo Sort --- src/sorting/README.md | 10 ++++++ src/sorting/bogo_bogo_sort.rs | 58 +++++++++++++++++++++++++++++++++++ src/sorting/mod.rs | 2 ++ 3 files changed, 70 insertions(+) create mode 100644 src/sorting/bogo_bogo_sort.rs diff --git a/src/sorting/README.md b/src/sorting/README.md index 4b0e248db35..a8e1c018fb8 100644 --- a/src/sorting/README.md +++ b/src/sorting/README.md @@ -10,6 +10,14 @@ __Properties__ * Best case performance O(n) * Average case performance O((n+1)!) +### [Bogo-Bogo-sort](./bogo_bogo_sort.rs) + +From [leonardini.dev][bogo-bogo-doc]: BogoBogo Sort is a humorously inefficient sorting algorithm inspired by the original Bogosort. It adds a layer of complexity by recursively sorting the first n-1 elements before placing the nth element. This process is repeated until the array is sorted. The algorithm's performance is exceptionally poor, making it impractical for sorting but a useful tool for educational purposes, especially in understanding algorithm efficiency and recursive functions. + +__Properties__ +* Worst case performance (unbounded, extremely poor) +* Best case performance O(n!) +* Average case performance (unpredictable and impractical) ### [Bubble](./bubble_sort.rs) ![alt text][bubble-image] @@ -208,6 +216,8 @@ __Properties__ [bogo-wiki]: https://en.wikipedia.org/wiki/Bogosort [bogo-image]: https://upload.wikimedia.org/wikipedia/commons/7/7b/Bogo_sort_animation.gif +[bogo-bogo-doc]: https://yaav.leonardini.dev/algorithms/sorting/bogobogo-sort.html + [bubble-toptal]: https://www.toptal.com/developers/sorting-algorithms/bubble-sort [bubble-wiki]: https://en.wikipedia.org/wiki/Bubble_sort [bubble-image]: https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Bubblesort-edited-color.svg/220px-Bubblesort-edited-color.svg.png "Bubble Sort" diff --git a/src/sorting/bogo_bogo_sort.rs b/src/sorting/bogo_bogo_sort.rs new file mode 100644 index 00000000000..1c2c350be15 --- /dev/null +++ b/src/sorting/bogo_bogo_sort.rs @@ -0,0 +1,58 @@ +use rand::seq::SliceRandom; +use rand::thread_rng; + +fn is_sorted(arr: &[T]) -> bool { + arr.windows(2).all(|w| w[0] <= w[1]) +} + +pub fn bogo_bogo_sort(arr: &[T]) -> Vec { + if arr.len() <= 1 { + return arr.to_vec(); + } + + let mut rng = thread_rng(); + let mut sorted_subarray = bogo_bogo_sort(&arr[..arr.len() - 1]); + + let mut extended_array = sorted_subarray.clone(); + extended_array.push(arr[arr.len() - 1].clone()); + + while !is_sorted(&extended_array) + || extended_array[arr.len() - 1] < *sorted_subarray.iter().max().unwrap() + { + extended_array.shuffle(&mut rng); + sorted_subarray = bogo_bogo_sort(&extended_array[..arr.len() - 1]); + extended_array = sorted_subarray.clone(); + extended_array.push(arr[arr.len() - 1].clone()); + } + + extended_array +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_sorted_array() { + let arr = vec![1, 2, 3, 4, 5]; + assert!(is_sorted(&bogo_bogo_sort(&arr))); + } + + #[test] + fn test_reverse_sorted_array() { + let arr = vec![5, 4, 3, 2, 1]; + assert!(is_sorted(&bogo_bogo_sort(&arr))); + } + + #[test] + fn test_unsorted_array() { + let arr = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]; + assert!(is_sorted(&bogo_bogo_sort(&arr))); + } + + #[test] + fn test_empty_array() { + let arr: Vec = vec![]; + assert!(is_sorted(&bogo_bogo_sort(&arr))); + } +} diff --git a/src/sorting/mod.rs b/src/sorting/mod.rs index 11486f36ab9..d39783d0e02 100644 --- a/src/sorting/mod.rs +++ b/src/sorting/mod.rs @@ -2,6 +2,7 @@ mod bead_sort; mod binary_insertion_sort; mod bingo_sort; mod bitonic_sort; +mod bogo_bogo_sort; mod bogo_sort; mod bubble_sort; mod bucket_sort; @@ -38,6 +39,7 @@ pub use self::bead_sort::bead_sort; pub use self::binary_insertion_sort::binary_insertion_sort; pub use self::bingo_sort::bingo_sort; pub use self::bitonic_sort::bitonic_sort; +pub use self::bogo_bogo_sort::bogo_bogo_sort; pub use self::bogo_sort::bogo_sort; pub use self::bubble_sort::bubble_sort; pub use self::bucket_sort::bucket_sort; From d8784c20250d99b9b80ba30efe607012a9b4519a Mon Sep 17 00:00:00 2001 From: Victor Moisa Date: Sun, 21 Jan 2024 02:39:47 +0200 Subject: [PATCH 2/6] Added several algorithms --- src/math/derrivative_method.rs | 93 ++++++++++++++++++++++++++++++++++ src/math/mod.rs | 2 + 2 files changed, 95 insertions(+) create mode 100644 src/math/derrivative_method.rs diff --git a/src/math/derrivative_method.rs b/src/math/derrivative_method.rs new file mode 100644 index 00000000000..5ccd7574e50 --- /dev/null +++ b/src/math/derrivative_method.rs @@ -0,0 +1,93 @@ +pub fn derivative_method(x: f64, y: f64, f: F) -> f64 +where + F: Fn(f64, f64) -> f64, +{ + let h = 0.0001; + (f(x + h, y) - f(x, y)) / h +} + +fn test_function(x: f64, y: f64) -> f64 { + x.powi(2) + y.powi(2) +} + +#[allow(dead_code)] +fn main() { + let x = 1.0; + let y = 2.0; + let f = test_function; + let df_dx = derivative_method(x, y, f); + let df_dy = derivative_method(y, x, f); + println!("df/dx = {}", df_dx); + println!("df/dy = {}", df_dy); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_derivative() { + let x = 1.0; + let y = 2.0; + let f = test_function; + let df_dx = derivative_method(x, y, f); + let df_dy = derivative_method(y, x, f); + assert_eq!(df_dx, 2.000100000003613); + assert_eq!(df_dy, 4.0001000000078335); + } + + #[test] + fn test_error() { + let x = 1.0; + let y = 2.0; + let f = test_function; + let df_dx = derivative_method(x, y, f); + let df_dy = derivative_method(y, x, f); + assert_ne!(df_dx, 2.0); + assert_ne!(df_dy, 4.0); + } + + #[test] + fn test_nan() { + let x = 1.0; + let y = 2.0; + let f = test_function; + let df_dx = derivative_method(x, y, f); + let df_dy = derivative_method(y, x, f); + assert!(!df_dx.is_nan()); + assert!(!df_dy.is_nan()); + } + + #[test] + fn test_inf() { + let x = 1.0; + let y = 2.0; + let f = test_function; + let df_dx = derivative_method(x, y, f); + let df_dy = derivative_method(y, x, f); + assert!(!df_dx.is_infinite()); + assert!(!df_dy.is_infinite()); + } + + #[test] + fn test_zero() { + let x = 1.0; + let y = 2.0; + let f = test_function; + let df_dx = derivative_method(x, y, f); + let df_dy = derivative_method(y, x, f); + assert_ne!(df_dx, 0.0); + assert_ne!(df_dy, 0.0); + } + + #[test] + fn test_subnormal() { + let x = 1.0; + let y = 2.0; + let f = test_function; + let df_dx = derivative_method(x, y, f); + let df_dy = derivative_method(y, x, f); + assert!(!df_dx.is_subnormal()); + assert!(!df_dy.is_subnormal()); + } +} diff --git a/src/math/mod.rs b/src/math/mod.rs index 0e225808e6a..2dfcccbf5b5 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -16,6 +16,7 @@ mod collatz_sequence; mod combinations; mod cross_entropy_loss; mod decimal_to_fraction; +mod derrivative_method; mod doomsday; mod elliptic_curve; mod euclidean_distance; @@ -98,6 +99,7 @@ pub use self::collatz_sequence::sequence; pub use self::combinations::combinations; pub use self::cross_entropy_loss::cross_entropy_loss; pub use self::decimal_to_fraction::decimal_to_fraction; +pub use self::derrivative_method::derivative_method; pub use self::doomsday::get_week_day; pub use self::elliptic_curve::EllipticCurve; pub use self::euclidean_distance::euclidean_distance; From ae15b6262cf757c15e749b3a29c2e39f0cdf8446 Mon Sep 17 00:00:00 2001 From: Victor Moisa Date: Sun, 21 Jan 2024 19:48:57 +0200 Subject: [PATCH 3/6] Added bogobogo sort --- src/sorting/README.md | 10 ++++++---- src/sorting/mod.rs | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sorting/README.md b/src/sorting/README.md index a8e1c018fb8..cb82089493a 100644 --- a/src/sorting/README.md +++ b/src/sorting/README.md @@ -11,8 +11,12 @@ __Properties__ * Average case performance O((n+1)!) ### [Bogo-Bogo-sort](./bogo_bogo_sort.rs) - -From [leonardini.dev][bogo-bogo-doc]: BogoBogo Sort is a humorously inefficient sorting algorithm inspired by the original Bogosort. It adds a layer of complexity by recursively sorting the first n-1 elements before placing the nth element. This process is repeated until the array is sorted. The algorithm's performance is exceptionally poor, making it impractical for sorting but a useful tool for educational purposes, especially in understanding algorithm efficiency and recursive functions. +From [leonardini.dev][bogo-bogo-doc]: BogoBogo Sort is a humorously inefficient sorting +algorithm inspired by the original Bogosort. It adds a layer of complexity by recursively +sorting the first n-1 elements before placing the nth element. This process is repeated until +the array is sorted. The algorithm's performance is exceptionally poor, making it impractical +for sorting but a useful tool for educational purposes, especially in understanding +algorithm efficiency and recursive functions. __Properties__ * Worst case performance (unbounded, extremely poor) @@ -216,8 +220,6 @@ __Properties__ [bogo-wiki]: https://en.wikipedia.org/wiki/Bogosort [bogo-image]: https://upload.wikimedia.org/wikipedia/commons/7/7b/Bogo_sort_animation.gif -[bogo-bogo-doc]: https://yaav.leonardini.dev/algorithms/sorting/bogobogo-sort.html - [bubble-toptal]: https://www.toptal.com/developers/sorting-algorithms/bubble-sort [bubble-wiki]: https://en.wikipedia.org/wiki/Bubble_sort [bubble-image]: https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Bubblesort-edited-color.svg/220px-Bubblesort-edited-color.svg.png "Bubble Sort" diff --git a/src/sorting/mod.rs b/src/sorting/mod.rs index d39783d0e02..4590201f98c 100644 --- a/src/sorting/mod.rs +++ b/src/sorting/mod.rs @@ -2,7 +2,6 @@ mod bead_sort; mod binary_insertion_sort; mod bingo_sort; mod bitonic_sort; -mod bogo_bogo_sort; mod bogo_sort; mod bubble_sort; mod bucket_sort; @@ -34,12 +33,13 @@ mod tim_sort; mod tree_sort; mod wave_sort; mod wiggle_sort; +mod bogo_bogo_sort; +pub use self::bogo_bogo_sort::bogo_bogo_sort; pub use self::bead_sort::bead_sort; pub use self::binary_insertion_sort::binary_insertion_sort; pub use self::bingo_sort::bingo_sort; pub use self::bitonic_sort::bitonic_sort; -pub use self::bogo_bogo_sort::bogo_bogo_sort; pub use self::bogo_sort::bogo_sort; pub use self::bubble_sort::bubble_sort; pub use self::bucket_sort::bucket_sort; From 5b61444bc365b5399e2fd131e88fb5e402802805 Mon Sep 17 00:00:00 2001 From: Victor Moisa Date: Sun, 21 Jan 2024 19:59:42 +0200 Subject: [PATCH 4/6] Added strand_sort --- src/sorting/README.md | 15 ++++- src/sorting/mod.rs | 4 +- src/sorting/strand_sort.rs | 124 +++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 src/sorting/strand_sort.rs diff --git a/src/sorting/README.md b/src/sorting/README.md index cb82089493a..4cce742c92d 100644 --- a/src/sorting/README.md +++ b/src/sorting/README.md @@ -215,7 +215,20 @@ This card game is turned into a two-phase sorting algorithm, as follows. Given a __Properties__ * Worst case performance O(n log n) -* Best case performance O(n) +* Best case performance O(n)\ + +### [Strand Sort](./strand_sort.rs) + +Strand Sort is a sorting algorithm that works by repeatedly pulling sorted sublists out of the list to be sorted and merging them with the already sorted part. It is particularly effective for sorting lists where there are large numbers of ordered elements. The algorithm is intuitive and simple, iterating through the list, picking up elements in order, and merging these 'strands' into a final sorted list. + +* Simplicity: The algorithm is straightforward and easy to implement, making it a good choice for introductory sorting algorithm education. +* Adaptive: Strand sort performs well on lists that are already partially sorted, as it can quickly identify and extract these ordered sublists. +* In-place Sorting: The nature of the algorithm allows it to be implemented in an in-place fashion, although this is not always the case. + +__Properties__ +* Not-in-place Sorting: Typically, strand sort requires additional space for the strands, though in-place variants exist. +* Time Complexity: The average and worst-case time complexity of strand sort can vary greatly depending on the input but typically is O(n²). +* Stability: The algorithm is stable, maintaining the relative order of equal elements. [bogo-wiki]: https://en.wikipedia.org/wiki/Bogosort [bogo-image]: https://upload.wikimedia.org/wikipedia/commons/7/7b/Bogo_sort_animation.gif diff --git a/src/sorting/mod.rs b/src/sorting/mod.rs index 4590201f98c..ced8a0c2619 100644 --- a/src/sorting/mod.rs +++ b/src/sorting/mod.rs @@ -29,13 +29,12 @@ mod sleep_sort; #[cfg(test)] mod sort_utils; mod stooge_sort; +mod strand_sort; mod tim_sort; mod tree_sort; mod wave_sort; mod wiggle_sort; -mod bogo_bogo_sort; -pub use self::bogo_bogo_sort::bogo_bogo_sort; pub use self::bead_sort::bead_sort; pub use self::binary_insertion_sort::binary_insertion_sort; pub use self::bingo_sort::bingo_sort; @@ -67,6 +66,7 @@ pub use self::selection_sort::selection_sort; pub use self::shell_sort::shell_sort; pub use self::sleep_sort::sleep_sort; pub use self::stooge_sort::stooge_sort; +pub use self::strand_sort::strand_sort; pub use self::tim_sort::tim_sort; pub use self::tree_sort::tree_sort; pub use self::wave_sort::wave_sort; diff --git a/src/sorting/strand_sort.rs b/src/sorting/strand_sort.rs new file mode 100644 index 00000000000..73c159b1aa1 --- /dev/null +++ b/src/sorting/strand_sort.rs @@ -0,0 +1,124 @@ +use std::collections::LinkedList; + +pub fn strand_sort(ip: &mut LinkedList, op: &mut LinkedList) { + if ip.is_empty() { + return; + } + + let mut sublist = LinkedList::new(); + sublist.push_back(ip.pop_front().unwrap()); + + let mut iter = ip.split_off(0); + while let Some(val) = iter.pop_front() { + if val > *sublist.back().unwrap() { + sublist.push_back(val); + } else { + ip.push_back(val); + } + } + + // Merge current sublist into output + let mut merged = LinkedList::new(); + while !op.is_empty() || !sublist.is_empty() { + match (op.front(), sublist.front()) { + (Some(&op_val), Some(&sub_val)) if op_val <= sub_val => { + merged.push_back(op.pop_front().unwrap()); + } + (_, Some(_)) => { + merged.push_back(sublist.pop_front().unwrap()); + } + (Some(_), _) => { + merged.push_back(op.pop_front().unwrap()); + } + (None, None) => break, + } + } + + *op = merged; + strand_sort(ip, op); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_strand_sort() { + let mut ip: LinkedList = LinkedList::from([10, 5, 30, 40, 2, 4, 9]); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_eq!(op, LinkedList::from([2, 4, 5, 9, 10, 30, 40])); + } + + #[test] + fn test_strand_sort_empty() { + let mut ip: LinkedList = LinkedList::new(); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_eq!(op, LinkedList::new()); + } + + #[test] + fn test_strand_sort_single() { + let mut ip: LinkedList = LinkedList::from([1]); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_eq!(op, LinkedList::from([1])); + } + + #[test] + fn test_strand_sort_negative() { + let mut ip: LinkedList = LinkedList::from([-1, -2, -3, -4, -5]); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_eq!(op, LinkedList::from([-5, -4, -3, -2, -1])); + } + + #[test] + fn test_strand_sort_duplicates() { + let mut ip: LinkedList = LinkedList::from([1, 1, 1, 1, 1]); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_eq!(op, LinkedList::from([1, 1, 1, 1, 1])); + } + + #[test] + fn test_strand_sort_error() { + let mut ip: LinkedList = LinkedList::from([1, 2, 3, 4, 5]); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_ne!(op, LinkedList::from([2, 1, 3, 4, 5])); + } + + #[test] + fn test_strand_sort_big() { + let mut ip: LinkedList = LinkedList::from([1, 2, 3, 4, 5, 6, 7, 8, 9]); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_eq!(op, LinkedList::from([1, 2, 3, 4, 5, 6, 7, 8, 9])); + } + + #[test] + fn test_strand_sort_big_reverse() { + let mut ip: LinkedList = LinkedList::from([9, 8, 7, 6, 5, 4, 3, 2, 1]); + let mut op: LinkedList = LinkedList::new(); + + strand_sort(&mut ip, &mut op); + + assert_eq!(op, LinkedList::from([1, 2, 3, 4, 5, 6, 7, 8, 9])); + } +} From 6dfa6bf0189c8cc5b5facb6e9453402ee568c706 Mon Sep 17 00:00:00 2001 From: Victor Moisa Date: Wed, 24 Jan 2024 22:48:42 +0200 Subject: [PATCH 5/6] Improved strand sort by changing mutability of function parameters and conformed file changes to pr review recommendation --- src/math/derrivative_method.rs | 93 --------------------- src/math/mod.rs | 2 - src/sorting/README.md | 13 --- src/sorting/bogo_bogo_sort.rs | 58 ------------- src/sorting/strand_sort.rs | 146 ++++++++++++++------------------- 5 files changed, 61 insertions(+), 251 deletions(-) delete mode 100644 src/math/derrivative_method.rs delete mode 100644 src/sorting/bogo_bogo_sort.rs diff --git a/src/math/derrivative_method.rs b/src/math/derrivative_method.rs deleted file mode 100644 index 5ccd7574e50..00000000000 --- a/src/math/derrivative_method.rs +++ /dev/null @@ -1,93 +0,0 @@ -pub fn derivative_method(x: f64, y: f64, f: F) -> f64 -where - F: Fn(f64, f64) -> f64, -{ - let h = 0.0001; - (f(x + h, y) - f(x, y)) / h -} - -fn test_function(x: f64, y: f64) -> f64 { - x.powi(2) + y.powi(2) -} - -#[allow(dead_code)] -fn main() { - let x = 1.0; - let y = 2.0; - let f = test_function; - let df_dx = derivative_method(x, y, f); - let df_dy = derivative_method(y, x, f); - println!("df/dx = {}", df_dx); - println!("df/dy = {}", df_dy); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_derivative() { - let x = 1.0; - let y = 2.0; - let f = test_function; - let df_dx = derivative_method(x, y, f); - let df_dy = derivative_method(y, x, f); - assert_eq!(df_dx, 2.000100000003613); - assert_eq!(df_dy, 4.0001000000078335); - } - - #[test] - fn test_error() { - let x = 1.0; - let y = 2.0; - let f = test_function; - let df_dx = derivative_method(x, y, f); - let df_dy = derivative_method(y, x, f); - assert_ne!(df_dx, 2.0); - assert_ne!(df_dy, 4.0); - } - - #[test] - fn test_nan() { - let x = 1.0; - let y = 2.0; - let f = test_function; - let df_dx = derivative_method(x, y, f); - let df_dy = derivative_method(y, x, f); - assert!(!df_dx.is_nan()); - assert!(!df_dy.is_nan()); - } - - #[test] - fn test_inf() { - let x = 1.0; - let y = 2.0; - let f = test_function; - let df_dx = derivative_method(x, y, f); - let df_dy = derivative_method(y, x, f); - assert!(!df_dx.is_infinite()); - assert!(!df_dy.is_infinite()); - } - - #[test] - fn test_zero() { - let x = 1.0; - let y = 2.0; - let f = test_function; - let df_dx = derivative_method(x, y, f); - let df_dy = derivative_method(y, x, f); - assert_ne!(df_dx, 0.0); - assert_ne!(df_dy, 0.0); - } - - #[test] - fn test_subnormal() { - let x = 1.0; - let y = 2.0; - let f = test_function; - let df_dx = derivative_method(x, y, f); - let df_dy = derivative_method(y, x, f); - assert!(!df_dx.is_subnormal()); - assert!(!df_dy.is_subnormal()); - } -} diff --git a/src/math/mod.rs b/src/math/mod.rs index 2dfcccbf5b5..0e225808e6a 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -16,7 +16,6 @@ mod collatz_sequence; mod combinations; mod cross_entropy_loss; mod decimal_to_fraction; -mod derrivative_method; mod doomsday; mod elliptic_curve; mod euclidean_distance; @@ -99,7 +98,6 @@ pub use self::collatz_sequence::sequence; pub use self::combinations::combinations; pub use self::cross_entropy_loss::cross_entropy_loss; pub use self::decimal_to_fraction::decimal_to_fraction; -pub use self::derrivative_method::derivative_method; pub use self::doomsday::get_week_day; pub use self::elliptic_curve::EllipticCurve; pub use self::euclidean_distance::euclidean_distance; diff --git a/src/sorting/README.md b/src/sorting/README.md index 4cce742c92d..f697dcca8bd 100644 --- a/src/sorting/README.md +++ b/src/sorting/README.md @@ -10,19 +10,6 @@ __Properties__ * Best case performance O(n) * Average case performance O((n+1)!) -### [Bogo-Bogo-sort](./bogo_bogo_sort.rs) -From [leonardini.dev][bogo-bogo-doc]: BogoBogo Sort is a humorously inefficient sorting -algorithm inspired by the original Bogosort. It adds a layer of complexity by recursively -sorting the first n-1 elements before placing the nth element. This process is repeated until -the array is sorted. The algorithm's performance is exceptionally poor, making it impractical -for sorting but a useful tool for educational purposes, especially in understanding -algorithm efficiency and recursive functions. - -__Properties__ -* Worst case performance (unbounded, extremely poor) -* Best case performance O(n!) -* Average case performance (unpredictable and impractical) - ### [Bubble](./bubble_sort.rs) ![alt text][bubble-image] diff --git a/src/sorting/bogo_bogo_sort.rs b/src/sorting/bogo_bogo_sort.rs deleted file mode 100644 index 1c2c350be15..00000000000 --- a/src/sorting/bogo_bogo_sort.rs +++ /dev/null @@ -1,58 +0,0 @@ -use rand::seq::SliceRandom; -use rand::thread_rng; - -fn is_sorted(arr: &[T]) -> bool { - arr.windows(2).all(|w| w[0] <= w[1]) -} - -pub fn bogo_bogo_sort(arr: &[T]) -> Vec { - if arr.len() <= 1 { - return arr.to_vec(); - } - - let mut rng = thread_rng(); - let mut sorted_subarray = bogo_bogo_sort(&arr[..arr.len() - 1]); - - let mut extended_array = sorted_subarray.clone(); - extended_array.push(arr[arr.len() - 1].clone()); - - while !is_sorted(&extended_array) - || extended_array[arr.len() - 1] < *sorted_subarray.iter().max().unwrap() - { - extended_array.shuffle(&mut rng); - sorted_subarray = bogo_bogo_sort(&extended_array[..arr.len() - 1]); - extended_array = sorted_subarray.clone(); - extended_array.push(arr[arr.len() - 1].clone()); - } - - extended_array -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_sorted_array() { - let arr = vec![1, 2, 3, 4, 5]; - assert!(is_sorted(&bogo_bogo_sort(&arr))); - } - - #[test] - fn test_reverse_sorted_array() { - let arr = vec![5, 4, 3, 2, 1]; - assert!(is_sorted(&bogo_bogo_sort(&arr))); - } - - #[test] - fn test_unsorted_array() { - let arr = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]; - assert!(is_sorted(&bogo_bogo_sort(&arr))); - } - - #[test] - fn test_empty_array() { - let arr: Vec = vec![]; - assert!(is_sorted(&bogo_bogo_sort(&arr))); - } -} diff --git a/src/sorting/strand_sort.rs b/src/sorting/strand_sort.rs index 73c159b1aa1..653cdcdbd22 100644 --- a/src/sorting/strand_sort.rs +++ b/src/sorting/strand_sort.rs @@ -1,124 +1,100 @@ use std::collections::LinkedList; -pub fn strand_sort(ip: &mut LinkedList, op: &mut LinkedList) { - if ip.is_empty() { - return; +pub fn strand_sort(list: &LinkedList) -> LinkedList { + if list.is_empty() { + return LinkedList::new(); } - let mut sublist = LinkedList::new(); - sublist.push_back(ip.pop_front().unwrap()); + let mut ip = list.clone(); + let mut op = LinkedList::new(); - let mut iter = ip.split_off(0); - while let Some(val) = iter.pop_front() { - if val > *sublist.back().unwrap() { - sublist.push_back(val); - } else { - ip.push_back(val); - } - } + while !ip.is_empty() { + let mut sublist = LinkedList::new(); + sublist.push_back(ip.pop_front().unwrap()); - // Merge current sublist into output - let mut merged = LinkedList::new(); - while !op.is_empty() || !sublist.is_empty() { - match (op.front(), sublist.front()) { - (Some(&op_val), Some(&sub_val)) if op_val <= sub_val => { - merged.push_back(op.pop_front().unwrap()); + let mut iter = ip.split_off(0); + while let Some(val) = iter.pop_front() { + if val >= *sublist.back().unwrap() { + sublist.push_back(val); + } else { + ip.push_back(val); } - (_, Some(_)) => { - merged.push_back(sublist.pop_front().unwrap()); - } - (Some(_), _) => { - merged.push_back(op.pop_front().unwrap()); + } + + // Merge current sublist into output + let mut merged = LinkedList::new(); + while !op.is_empty() || !sublist.is_empty() { + match (op.front(), sublist.front()) { + (Some(&op_val), Some(&sub_val)) if op_val <= sub_val => { + merged.push_back(op.pop_front().unwrap()); + } + (_, Some(_)) => { + merged.push_back(sublist.pop_front().unwrap()); + } + (Some(_), _) => { + merged.push_back(op.pop_front().unwrap()); + } + (None, None) => break, } - (None, None) => break, } + + op = merged; } - *op = merged; - strand_sort(ip, op); + op } #[cfg(test)] mod tests { use super::*; + use std::collections::LinkedList; #[test] - fn test_strand_sort() { - let mut ip: LinkedList = LinkedList::from([10, 5, 30, 40, 2, 4, 9]); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_eq!(op, LinkedList::from([2, 4, 5, 9, 10, 30, 40])); + fn test_strand_sort_basic() { + let ip = LinkedList::from([10, 5, 30, 40, 2, 4, 9]); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::from([2, 4, 5, 9, 10, 30, 40])); } #[test] fn test_strand_sort_empty() { - let mut ip: LinkedList = LinkedList::new(); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_eq!(op, LinkedList::new()); + let ip = LinkedList::new(); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::new()); } #[test] - fn test_strand_sort_single() { - let mut ip: LinkedList = LinkedList::from([1]); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_eq!(op, LinkedList::from([1])); + fn test_strand_sort_single_element() { + let ip = LinkedList::from([1]); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::from([1])); } #[test] - fn test_strand_sort_negative() { - let mut ip: LinkedList = LinkedList::from([-1, -2, -3, -4, -5]); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_eq!(op, LinkedList::from([-5, -4, -3, -2, -1])); - } - - #[test] - fn test_strand_sort_duplicates() { - let mut ip: LinkedList = LinkedList::from([1, 1, 1, 1, 1]); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_eq!(op, LinkedList::from([1, 1, 1, 1, 1])); + fn test_strand_sort_negative_numbers() { + let ip = LinkedList::from([-1, -2, -3, -4, -5]); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::from([-5, -4, -3, -2, -1])); } #[test] - fn test_strand_sort_error() { - let mut ip: LinkedList = LinkedList::from([1, 2, 3, 4, 5]); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_ne!(op, LinkedList::from([2, 1, 3, 4, 5])); + fn test_strand_sort_with_duplicates() { + let ip = LinkedList::from([1, 1, 1, 1, 1]); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::from([1, 1, 1, 1, 1])); } #[test] - fn test_strand_sort_big() { - let mut ip: LinkedList = LinkedList::from([1, 2, 3, 4, 5, 6, 7, 8, 9]); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_eq!(op, LinkedList::from([1, 2, 3, 4, 5, 6, 7, 8, 9])); + fn test_strand_sort_sorted_input() { + let ip = LinkedList::from([1, 2, 3, 4, 5]); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::from([1, 2, 3, 4, 5])); } #[test] - fn test_strand_sort_big_reverse() { - let mut ip: LinkedList = LinkedList::from([9, 8, 7, 6, 5, 4, 3, 2, 1]); - let mut op: LinkedList = LinkedList::new(); - - strand_sort(&mut ip, &mut op); - - assert_eq!(op, LinkedList::from([1, 2, 3, 4, 5, 6, 7, 8, 9])); + fn test_strand_sort_reverse_sorted_input() { + let ip = LinkedList::from([5, 4, 3, 2, 1]); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::from([1, 2, 3, 4, 5])); } } From 557119bf6daada2044a454f7d50b100e95bf7a67 Mon Sep 17 00:00:00 2001 From: Victor Moisa Date: Thu, 25 Jan 2024 14:08:25 +0200 Subject: [PATCH 6/6] Added requested test and attempted to change use of clone --- src/sorting/strand_sort.rs | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/sorting/strand_sort.rs b/src/sorting/strand_sort.rs index 653cdcdbd22..c7506f54934 100644 --- a/src/sorting/strand_sort.rs +++ b/src/sorting/strand_sort.rs @@ -5,40 +5,35 @@ pub fn strand_sort(list: &LinkedList) -> LinkedList { return LinkedList::new(); } - let mut ip = list.clone(); + let mut ip = list.iter().cloned().collect::>(); let mut op = LinkedList::new(); while !ip.is_empty() { let mut sublist = LinkedList::new(); sublist.push_back(ip.pop_front().unwrap()); - let mut iter = ip.split_off(0); - while let Some(val) = iter.pop_front() { + let mut temp_list = LinkedList::new(); + while let Some(val) = ip.pop_front() { if val >= *sublist.back().unwrap() { sublist.push_back(val); } else { - ip.push_back(val); + temp_list.push_back(val); } } - // Merge current sublist into output let mut merged = LinkedList::new(); - while !op.is_empty() || !sublist.is_empty() { - match (op.front(), sublist.front()) { - (Some(&op_val), Some(&sub_val)) if op_val <= sub_val => { - merged.push_back(op.pop_front().unwrap()); - } - (_, Some(_)) => { - merged.push_back(sublist.pop_front().unwrap()); - } - (Some(_), _) => { - merged.push_back(op.pop_front().unwrap()); - } - (None, None) => break, + while let (Some(&op_val), Some(&sub_val)) = (op.front(), sublist.front()) { + if op_val <= sub_val { + merged.push_back(op.pop_front().unwrap()); + } else { + merged.push_back(sublist.pop_front().unwrap()); } } + merged.append(&mut op); + merged.append(&mut sublist); op = merged; + ip = temp_list; } op @@ -97,4 +92,11 @@ mod tests { let result = strand_sort(&ip); assert_eq!(result, LinkedList::from([1, 2, 3, 4, 5])); } + + #[test] + fn test_strand_sort_interleaved_merge() { + let ip = LinkedList::from([4, 1, 5, 2, 6, 3]); + let result = strand_sort(&ip); + assert_eq!(result, LinkedList::from([1, 2, 3, 4, 5, 6])); + } }