use std::fmt::Debug;
pub fn sort<T>(slice: &mut [T])
where
T: PartialOrd + Clone + Debug,
{
let len = slice.len();
if len <= 1 {
return;
}
let mut gap = calculate_initial_gap(len);
while gap > 0 {
for i in gap..len {
let mut j = i;
while j >= gap
&& slice[j - gap].partial_cmp(&slice[j]).unwrap() == std::cmp::Ordering::Greater
{
slice.swap(j - gap, j);
j -= gap;
}
}
gap = if gap == 2 { 1 } else { gap / 3 };
}
}
fn calculate_initial_gap(len: usize) -> usize {
let mut gap = 1;
while gap < len / 3 {
gap = 3 * gap + 1;
}
gap
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_slice() {
let mut arr: Vec<i32> = vec![];
sort(&mut arr);
assert_eq!(arr, Vec::<i32>::new());
}
#[test]
fn test_single_element() {
let mut arr = vec![1];
sort(&mut arr);
assert_eq!(arr, vec![1]);
}
#[test]
fn test_sorted_array() {
let mut arr = vec![1, 2, 3, 4, 5];
sort(&mut arr);
assert_eq!(arr, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_reverse_sorted() {
let mut arr = vec![5, 4, 3, 2, 1];
sort(&mut arr);
assert_eq!(arr, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_random_order() {
let mut arr = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
let mut expected = arr.clone();
expected.sort();
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_duplicate_elements() {
let mut arr = vec![3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
let mut expected = arr.clone();
expected.sort();
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_large_array() {
let mut arr: Vec<i32> = (0..1000).rev().collect();
let mut expected = arr.clone();
expected.sort();
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_different_types() {
let mut float_arr = vec![3.14, 1.41, 2.71, 0.58];
let mut expected = float_arr.clone();
expected.sort_by(|a, b| a.partial_cmp(b).unwrap());
sort(&mut float_arr);
assert_eq!(float_arr, expected);
let mut string_arr = vec!["banana", "apple", "cherry", "date"];
let mut expected = string_arr.clone();
expected.sort();
sort(&mut string_arr);
assert_eq!(string_arr, expected);
}
#[test]
fn test_all_equal() {
let mut arr = vec![1, 1, 1, 1, 1];
sort(&mut arr);
assert_eq!(arr, vec![1, 1, 1, 1, 1]);
}
#[test]
fn test_alternating() {
let mut arr = vec![1, 2, 1, 2, 1, 2];
sort(&mut arr);
assert_eq!(arr, vec![1, 1, 1, 2, 2, 2]);
}
#[test]
fn test_negative_numbers() {
let mut arr = vec![-5, -2, -8, -1, -9];
sort(&mut arr);
assert_eq!(arr, vec![-9, -8, -5, -2, -1]);
}
#[test]
fn test_mixed_numbers() {
let mut arr = vec![-3, 4, 0, -1, 5, -2];
sort(&mut arr);
assert_eq!(arr, vec![-3, -2, -1, 0, 4, 5]);
}
#[test]
fn test_partially_sorted() {
let mut arr = vec![1, 2, 4, 3, 5, 7, 6, 8];
sort(&mut arr);
assert_eq!(arr, vec![1, 2, 3, 4, 5, 6, 7, 8]);
}
#[test]
fn test_gap_sequence() {
let sizes = vec![10, 100, 1000];
for size in sizes {
let gap = calculate_initial_gap(size);
assert!(gap > 0, "Gap should be positive for size {}", size);
assert!(gap < size, "Gap should be less than array size {}", size);
}
}
#[test]
fn test_knuth_sequence() {
let n = 100;
let mut gap = 1;
let mut gaps = vec![gap];
while gap * 3 + 1 < n {
gap = gap * 3 + 1;
gaps.push(gap);
}
for i in 0..gaps.len() - 1 {
assert!(gaps[i] < gaps[i + 1], "Gaps should be in increasing order");
}
assert!(
gaps.last().unwrap() < &n,
"Largest gap should be less than array size"
);
}
}