From cc822b9f04b68dd6b9e786982bf62fc5cbeed66f Mon Sep 17 00:00:00 2001 From: jacekpoz Date: Mon, 6 May 2024 21:13:20 +0200 Subject: [PATCH] refactor zad2 and 3 from lab2 --- lab2/zad2/Cargo.toml | 4 +- lab2/zad2/src/main.rs | 44 ++++--- lab2/zad3/Cargo.toml | 4 +- lab2/zad3/src/main.rs | 54 +++++---- lab2/zad4/Cargo.toml | 4 +- lab2/zad4/src/main.rs | 164 +++++---------------------- libsort/src/dual_pivot_quick_sort.rs | 139 +++++++++++++++++++++++ libsort/src/lib.rs | 3 + libsort/src/merge_sort.rs | 95 ++++++++++++++++ libsort/src/my_sort.rs | 137 ++++++++++++++++++++++ 10 files changed, 471 insertions(+), 177 deletions(-) create mode 100644 libsort/src/dual_pivot_quick_sort.rs create mode 100644 libsort/src/merge_sort.rs create mode 100644 libsort/src/my_sort.rs diff --git a/lab2/zad2/Cargo.toml b/lab2/zad2/Cargo.toml index a7c2510..64d99f1 100644 --- a/lab2/zad2/Cargo.toml +++ b/lab2/zad2/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -libsort = { path = "../zad1/libsort" } -libgen = { path = "../zad1/libgen" } +libsort = { path = "../../libsort" } +libgen = { path = "../../libgen" } diff --git a/lab2/zad2/src/main.rs b/lab2/zad2/src/main.rs index acd039e..bc2ae0a 100644 --- a/lab2/zad2/src/main.rs +++ b/lab2/zad2/src/main.rs @@ -2,22 +2,22 @@ use std::{collections::HashMap, env::args, fs::{self, OpenOptions}, sync::{Arc, use std::io::{self, Write}; use libgen::gen_rand; -use libsort::{hybrid_sort, insertion_sort, quick_sort, SortResult}; +use libsort::{hybrid_sort::HybridSort, insertion_sort::InsertionSort, quick_sort::QuickSort, Sort}; -fn comp_avg(results_map: &HashMap>) -> HashMap { +fn comp_avg(results_map: &HashMap>) -> HashMap { results_map.iter() .map(|(i, results)| (*i, (results.iter() - .map(|res| res.comparisons) + .map(|res| res.0) .sum::() as f64 / results.len() as f64))) .collect() } -fn swap_avg(results_map: &HashMap>) -> HashMap { +fn swap_avg(results_map: &HashMap>) -> HashMap { results_map.iter() .map(|(i, results)| (*i, (results.iter() - .map(|res| res.swaps) + .map(|res| res.1) .sum::() as f64 / results.len() as f64))) .collect() } @@ -28,12 +28,12 @@ fn main() -> io::Result<()> { .parse::() .expect("k must be u64"); - let insertion_results_small: Arc>>> = Arc::new(RwLock::new(HashMap::new())); - let quick_results_small: Arc>>> = Arc::new(RwLock::new(HashMap::new())); - let hybrid_results_small: Arc>>> = Arc::new(RwLock::new(HashMap::new())); + let insertion_results_small: Arc>>> = Arc::new(RwLock::new(HashMap::new())); + let quick_results_small: Arc>>> = Arc::new(RwLock::new(HashMap::new())); + let hybrid_results_small: Arc>>> = Arc::new(RwLock::new(HashMap::new())); - let quick_results_large: Arc>>> = Arc::new(RwLock::new(HashMap::new())); - let hybrid_results_large: Arc>>> = Arc::new(RwLock::new(HashMap::new())); + let quick_results_large: Arc>>> = Arc::new(RwLock::new(HashMap::new())); + let hybrid_results_large: Arc>>> = Arc::new(RwLock::new(HashMap::new())); let mut thread_handles = vec![]; @@ -64,10 +64,18 @@ fn main() -> io::Result<()> { irs.insert(n as u64, vec![]); qrs.insert(n as u64, vec![]); hrs.insert(n as u64, vec![]); + + let mut insertion = InsertionSort::new(false); + let mut quick = QuickSort::new(false); + let mut hybrid = HybridSort::new(8, false); for _ in 0..k { - irs.get_mut(&(n as u64)).unwrap().push(insertion_sort(&mut gen_rand(n as u64), false)); - qrs.get_mut(&(n as u64)).unwrap().push(quick_sort(&mut gen_rand(n as u64), false)); - hrs.get_mut(&(n as u64)).unwrap().push(hybrid_sort(&mut gen_rand(n as u64), 8, false)); + insertion.sort_mut(&mut gen_rand(n as u64)); + quick.sort_mut(&mut gen_rand(n as u64)); + hybrid.sort_mut(&mut gen_rand(n as u64)); + + irs.get_mut(&(n as u64)).unwrap().push((insertion.num_comp(), insertion.num_swap())); + qrs.get_mut(&(n as u64)).unwrap().push((quick.num_comp(), quick.num_swap())); + hrs.get_mut(&(n as u64)).unwrap().push((hybrid.num_comp(), hybrid.num_swap())); } } }); @@ -90,9 +98,15 @@ fn main() -> io::Result<()> { qrl.insert(n as u64, vec![]); hrl.insert(n as u64, vec![]); + + let mut quick = QuickSort::new(false); + let mut hybrid = HybridSort::new(8, false); for _ in 0..k { - qrl.get_mut(&(n as u64)).unwrap().push(quick_sort(&mut gen_rand(n as u64), false)); - hrl.get_mut(&(n as u64)).unwrap().push(hybrid_sort(&mut gen_rand(n as u64), 8, false)); + quick.sort_mut(&mut gen_rand(n as u64)); + hybrid.sort_mut(&mut gen_rand(n as u64)); + + qrl.get_mut(&(n as u64)).unwrap().push((quick.num_comp(), quick.num_swap())); + hrl.get_mut(&(n as u64)).unwrap().push((hybrid.num_comp(), hybrid.num_swap())); } } }); diff --git a/lab2/zad3/Cargo.toml b/lab2/zad3/Cargo.toml index 3ad7379..29ecc13 100644 --- a/lab2/zad3/Cargo.toml +++ b/lab2/zad3/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -libgen = { path = "../zad1/libgen" } -libsort = { path = "../zad1/libsort" } +libgen = { path = "../../libgen" } +libsort = { path = "../../libsort" } diff --git a/lab2/zad3/src/main.rs b/lab2/zad3/src/main.rs index 9d6e5e3..4a912bb 100644 --- a/lab2/zad3/src/main.rs +++ b/lab2/zad3/src/main.rs @@ -5,25 +5,25 @@ mod mysort; use std::{collections::HashMap, env::args, fs::{self, OpenOptions}, io::{self, Write}}; use libgen::gen_rand; -use libsort::{is_sorted, print_list, SortResult}; +use libsort::{is_sorted, merge_sort::MergeSort, my_sort::MySort, Sort}; use mergesort::mergesort; use crate::mysort::mysort; -fn comp_avg(results_map: &HashMap>) -> HashMap { +fn comp_avg(results_map: &HashMap>) -> HashMap { results_map.iter() .map(|(i, results)| (*i, (results.iter() - .map(|res| res.comparisons) + .map(|res| res.0) .sum::() as f64 / results.len() as f64))) .collect() } -fn swap_avg(results_map: &HashMap>) -> HashMap { +fn swap_avg(results_map: &HashMap>) -> HashMap { results_map.iter() .map(|(i, results)| (*i, (results.iter() - .map(|res| res.swaps) + .map(|res| res.1) .sum::() as f64 / results.len() as f64))) .collect() } @@ -55,23 +55,25 @@ fn sort_stdin() -> io::Result<()> { if print { print!("input: "); - print_list(&input_list); + println!("{:?}", input_list); println!(); } - let res = mysort(&mut list); + let mut my = MySort::new(print); + + my.sort_mut(&mut list); if print { println!(); print!("input: "); - print_list(&input_list); + println!("{:?}", input_list); println!(); print!("output: "); - print_list(&list); + println!("{:?}", list); } - println!("swaps: {}", res.swaps); - println!("comparisons: {}", res.comparisons); + println!("swaps: {}", my.num_swap()); + println!("comparisons: {}", my.num_comp()); println!("is sorted: {}", is_sorted(&list)); @@ -88,31 +90,37 @@ fn main() -> io::Result<()> { .parse::() .expect("k must be u64"); - let mut merge_results_small: HashMap> = HashMap::new(); - let mut my_results_small: HashMap> = HashMap::new(); + let mut merge_results_small: HashMap> = HashMap::new(); + let mut my_results_small: HashMap> = HashMap::new(); for n in (10..=50).step_by(10) { merge_results_small.insert(n, vec![]); my_results_small.insert(n, vec![]); + + let mut merge = MergeSort::new(false); + let mut my = MySort::new(false); for _ in 0..k { - let mut res = SortResult::default(); - mergesort(&mut gen_rand(n), &mut res); - merge_results_small.get_mut(&n).unwrap().push(res); - my_results_small.get_mut(&n).unwrap().push(mysort(&mut gen_rand(n))); + merge.sort_mut(&mut gen_rand(n)); + my.sort_mut(&mut gen_rand(n)); + merge_results_small.get_mut(&n).unwrap().push((merge.num_comp(), merge.num_swap())); + my_results_small.get_mut(&n).unwrap().push((my.num_comp(), my.num_swap())); } } - let mut merge_results_large: HashMap> = HashMap::new(); - let mut my_results_large: HashMap> = HashMap::new(); + let mut merge_results_large: HashMap> = HashMap::new(); + let mut my_results_large: HashMap> = HashMap::new(); for n in (1000..=50000).step_by(1000) { merge_results_large.insert(n, vec![]); my_results_large.insert(n, vec![]); + + let mut merge = MergeSort::new(false); + let mut my = MySort::new(false); for _ in 0..k { - let mut res = SortResult::default(); - mergesort(&mut gen_rand(n), &mut res); - merge_results_large.get_mut(&n).unwrap().push(res); - my_results_large.get_mut(&n).unwrap().push(mysort(&mut gen_rand(n))); + merge.sort_mut(&mut gen_rand(n)); + my.sort_mut(&mut gen_rand(n)); + merge_results_large.get_mut(&n).unwrap().push((merge.num_comp(), merge.num_swap())); + my_results_large.get_mut(&n).unwrap().push((my.num_comp(), my.num_swap())); } } diff --git a/lab2/zad4/Cargo.toml b/lab2/zad4/Cargo.toml index fb903fa..66abb99 100644 --- a/lab2/zad4/Cargo.toml +++ b/lab2/zad4/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -libgen = { path = "../zad1/libgen" } -libsort = { path = "../zad1/libsort" } +libgen = { path = "../../libgen" } +libsort = { path = "../../libsort" } diff --git a/lab2/zad4/src/main.rs b/lab2/zad4/src/main.rs index 348c875..927af95 100644 --- a/lab2/zad4/src/main.rs +++ b/lab2/zad4/src/main.rs @@ -1,136 +1,22 @@ use std::{collections::HashMap, env::args, fs::{self, OpenOptions}, io::{self, Write}}; use libgen::gen_rand; -use libsort::{is_sorted, print_list, quick_sort, SortResult}; +use libsort::{dual_pivot_quick_sort::DualPivotQuickSort, is_sorted, quick_sort::{self, QuickSort}, Sort}; -#[derive(PartialEq)] -enum CompareResult { - LESS, EQUAL, GREATER -} - -fn compare(a: u64, b: u64, comparisons: &mut u64) -> CompareResult { - *comparisons += 1; - if a < b { - CompareResult::LESS - } else if a > b { - CompareResult::GREATER - } else { - CompareResult::EQUAL - } -} - -fn swap(list: &mut [u64], i: usize, j: usize, swaps: &mut u64) { - *swaps += 1; - list.swap(i, j); -} - -use CompareResult::*; - -fn dual_pivot_partition(list: &mut [u64], res: &mut SortResult) -> (usize, usize) { - - let mut comps = 0; - let mut swaps = 0; - if compare(list[0], list[list.len() - 1], &mut comps) == GREATER { - swap(list, 0, list.len() - 1, &mut swaps); - } - - let mut l = 1; - let mut g = list.len() - 2; - let mut k = l; - let p = list[0]; - let q = list[list.len() - 1]; - - while k <= g { - // l > s - if ((list.len() - 1) - g) > (l - 1) { - // list[k] >= q - if compare(list[k], q, &mut comps) != LESS { - while compare(list[g], q, &mut comps) == GREATER && k < g { - g -= 1; - } - swap(list, k, g, &mut swaps); - g -= 1; - if compare(list[k], p, &mut comps) == LESS { - swap(list, k, l, &mut swaps); - l += 1; - } - // list[k] < p - } else if compare(list[k], p, &mut comps) == LESS { - swap(list, k, l, &mut swaps); - l += 1; - } - // l < s - } else { - // list[k] < p - if compare(list[k], p, &mut comps) == LESS { - swap(list, k, l, &mut swaps); - l += 1; - // list[k] >= q - } else if compare(list[k], q, &mut comps) != LESS { - while compare(list[g], q, &mut comps) == GREATER && k < g { - g -= 1; - } - swap(list, k, g, &mut swaps); - g -= 1; - if compare(list[k], p, &mut comps) == LESS { - swap(list, k, l, &mut swaps); - l += 1; - } - } - } - k += 1; - } - - l -= 1; - g += 1; - - swap(list, 0, l, &mut swaps); - swap(list, list.len() - 1, g, &mut swaps); - - res.comparisons += comps; - res.swaps += swaps; - - (l, g) -} - -fn dual_pivot_quick_sort(list: &mut [u64], print: bool) -> SortResult { - let mut res = SortResult::default(); - - if list.len() <= 1 { - return res; - } - - let (lp, rp) = dual_pivot_partition(list, &mut res); - - if print { - println!("left pivot = {lp}; right pivot = {rp}:"); - print_list(&list); - } - - let res1 = if lp == 0 { res.clone() } else { dual_pivot_quick_sort(&mut list[0..=(lp - 1)], print) }; - let res2 = dual_pivot_quick_sort(&mut list[(lp + 1)..=(rp - 1)], print); - let res3 = dual_pivot_quick_sort(&mut list[(rp + 1)..], print); - - res.comparisons += res1.comparisons + res2.comparisons + res3.comparisons; - res.swaps += res1.swaps + res2.swaps + res3.swaps; - - res -} - -fn comp_avg(results_map: &HashMap>) -> HashMap { +fn comp_avg(results_map: &HashMap>) -> HashMap { results_map.iter() .map(|(i, results)| (*i, (results.iter() - .map(|res| res.comparisons) + .map(|res| res.0) .sum::() as f64 / results.len() as f64))) .collect() } -fn swap_avg(results_map: &HashMap>) -> HashMap { +fn swap_avg(results_map: &HashMap>) -> HashMap { results_map.iter() .map(|(i, results)| (*i, (results.iter() - .map(|res| res.swaps) + .map(|res| res.1) .sum::() as f64 / results.len() as f64))) .collect() } @@ -162,23 +48,25 @@ fn sort_stdin() -> io::Result<()> { if print { print!("input: "); - print_list(&input_list); + println!("{:?}", input_list); println!(); } - let res = dual_pivot_quick_sort(&mut list, print); + let mut dual_pivot_quick = DualPivotQuickSort::new(print); + + dual_pivot_quick.sort_mut(&mut list); if print { println!(); print!("input: "); - print_list(&input_list); + println!("{:?}", input_list); println!(); print!("output: "); - print_list(&list); + println!("{:?}", list); } - println!("swaps: {}", res.swaps); - println!("comparisons: {}", res.comparisons); + println!("swaps: {}", dual_pivot_quick.num_swap()); + println!("comparisons: {}", dual_pivot_quick.num_comp()); println!("is sorted: {}", is_sorted(&list)); @@ -195,27 +83,37 @@ fn main() -> io::Result<()> { .parse::() .expect("k must be u64"); - let mut quick_results_small: HashMap> = HashMap::new(); - let mut dual_pivot_results_small: HashMap> = HashMap::new(); + let mut quick_results_small: HashMap> = HashMap::new(); + let mut dual_pivot_results_small: HashMap> = HashMap::new(); for n in (10..=50).step_by(10) { quick_results_small.insert(n, vec![]); dual_pivot_results_small.insert(n, vec![]); + + let mut quick = QuickSort::new(false); + let mut dual_pivot_quick = DualPivotQuickSort::new(false); for _ in 0..k { - quick_results_small.get_mut(&n).unwrap().push(quick_sort(&mut gen_rand(n), false)); - dual_pivot_results_small.get_mut(&n).unwrap().push(dual_pivot_quick_sort(&mut gen_rand(n), false)); + quick.sort_mut(&mut gen_rand(n)); + dual_pivot_quick.sort_mut(&mut gen_rand(n)); + quick_results_small.get_mut(&n).unwrap().push((quick.num_comp(), quick.num_swap())); + dual_pivot_results_small.get_mut(&n).unwrap().push((dual_pivot_quick.num_comp(), dual_pivot_quick.num_swap())); } } - let mut quick_results_large: HashMap> = HashMap::new(); - let mut dual_pivot_results_large: HashMap> = HashMap::new(); + let mut quick_results_large: HashMap> = HashMap::new(); + let mut dual_pivot_results_large: HashMap> = HashMap::new(); for n in (1000..=50000).step_by(1000) { quick_results_large.insert(n, vec![]); dual_pivot_results_large.insert(n, vec![]); + + let mut quick = QuickSort::new(false); + let mut dual_pivot_quick = DualPivotQuickSort::new(false); for _ in 0..k { - quick_results_large.get_mut(&n).unwrap().push(quick_sort(&mut gen_rand(n), false)); - dual_pivot_results_large.get_mut(&n).unwrap().push(dual_pivot_quick_sort(&mut gen_rand(n), false)); + quick.sort_mut(&mut gen_rand(n)); + dual_pivot_quick.sort_mut(&mut gen_rand(n)); + quick_results_large.get_mut(&n).unwrap().push((quick.num_comp(), quick.num_swap())); + dual_pivot_results_large.get_mut(&n).unwrap().push((dual_pivot_quick.num_comp(), dual_pivot_quick.num_swap())); } } diff --git a/libsort/src/dual_pivot_quick_sort.rs b/libsort/src/dual_pivot_quick_sort.rs new file mode 100644 index 0000000..4d0b7f6 --- /dev/null +++ b/libsort/src/dual_pivot_quick_sort.rs @@ -0,0 +1,139 @@ +use crate::{CompareResult, Sort}; + +pub struct DualPivotQuickSort { + comparisons: u64, + swaps: u64, + should_print: bool, +} + +impl DualPivotQuickSort { + fn swap(&mut self, list: &mut Vec, i: usize, j: usize) { + self.swaps += 1; + list.swap(i, j); + } + fn compare(&mut self, a: u64, b: u64) -> CompareResult { + self.comparisons += 1; + if a < b { + CompareResult::LESS + } else if a > b { + CompareResult::GREATER + } else { + CompareResult::EQUAL + } + } + + fn dual_pivot_partition(&mut self, list: &mut Vec) -> (usize, usize) { + + use CompareResult::*; + if self.compare(list[0], list[list.len() - 1]) == GREATER { + self.swap(list, 0, list.len() - 1); + } + + let mut l = 1; + let mut g = list.len() - 2; + let mut k = l; + let p = list[0]; + let q = list[list.len() - 1]; + + while k <= g { + // l > s + if ((list.len() - 1) - g) > (l - 1) { + // list[k] >= q + if self.compare(list[k], q) != LESS { + while self.compare(list[g], q) == GREATER && k < g { + g -= 1; + } + self.swap(list, k, g); + g -= 1; + if self.compare(list[k], p) == LESS { + self.swap(list, k, l); + l += 1; + } + // list[k] < p + } else if self.compare(list[k], p) == LESS { + self.swap(list, k, l); + l += 1; + } + // l < s + } else { + // list[k] < p + if self.compare(list[k], p) == LESS { + self.swap(list, k, l); + l += 1; + // list[k] >= q + } else if self.compare(list[k], q) != LESS { + while self.compare(list[g], q) == GREATER && k < g { + g -= 1; + } + self.swap(list, k, g); + g -= 1; + if self.compare(list[k], p) == LESS { + self.swap(list, k, l); + l += 1; + } + } + } + k += 1; + } + + l -= 1; + g += 1; + + self.swap(list, 0, l); + self.swap(list, list.len() - 1, g); + + (l, g) + } +} + +impl Sort for DualPivotQuickSort { + fn new(should_print: bool) -> Self { + Self { + comparisons: 0, + swaps: 0, + should_print, + } + } + + fn sort_mut(&mut self, list: &mut Vec) { + + if list.len() <= 1 { + return; + } + + let (lp, rp) = self.dual_pivot_partition(list); + + if self.should_print { + println!("left pivot = {lp}; right pivot = {rp}:"); + println!("{:?}", list); + } + + let mut vec = list.clone(); + vec.drain(lp..); + self.sort_mut(&mut vec); + + let mut vec = list.clone(); + vec.drain(rp..); + vec.drain(..=lp); + self.sort_mut(&mut vec); + + let mut vec = list.clone(); + vec.drain(..=rp); + self.sort_mut(&mut vec); + } + + fn num_comp(&self) -> u64 { + self.comparisons + } + + fn num_swap(&self) -> u64 { + self.swaps + } + + fn reset_state(&mut self) { + self.comparisons = 0; + self.swaps = 0; + } +} + + diff --git a/libsort/src/lib.rs b/libsort/src/lib.rs index d0828a2..8ee5220 100644 --- a/libsort/src/lib.rs +++ b/libsort/src/lib.rs @@ -1,5 +1,8 @@ pub mod insertion_sort; +pub mod dual_pivot_quick_sort; pub mod hybrid_sort; +pub mod merge_sort; +pub mod my_sort; pub mod quick_sort; pub trait Sort { diff --git a/libsort/src/merge_sort.rs b/libsort/src/merge_sort.rs new file mode 100644 index 0000000..74c65d9 --- /dev/null +++ b/libsort/src/merge_sort.rs @@ -0,0 +1,95 @@ +use crate::{CompareResult, Sort}; + +pub struct MergeSort { + comparisons: u64, + swaps: u64, +} + +impl MergeSort { + fn compare(&mut self, a: u64, b: u64) -> CompareResult { + self.comparisons += 1; + if a < b { + CompareResult::LESS + } else if a > b { + CompareResult::GREATER + } else { + CompareResult::EQUAL + } + } + + pub fn merge(&mut self, list1: &Vec, list2: &Vec) -> Vec { + let mut ret = vec![]; + + let mut i = 0; + let mut j = 0; + + while i < list1.len() && j < list2.len() { + use CompareResult::*; + if self.compare(list1[i], list2[j]) == LESS { + ret.push(list1[i]); + i = i + 1; + } else { + ret.push(list2[j]); + j = j + 1; + } + } + + if i < list1.len() { + while i < list1.len() { + ret.push(list1[i]); + i = i + 1; + } + } + + if j < list2.len() { + while j < list2.len() { + ret.push(list2[j]); + j = j + 1; + } + } + + ret + } +} + +impl Sort for MergeSort { + fn new(_should_print: bool) -> Self { + Self { + comparisons: 0, + swaps: 0, + } + } + + fn sort_mut(&mut self, list: &mut Vec) { + + if list.len() > 1 { + let size = list.len() / 2; + + let mut vec = list.clone(); + vec.drain(size..); + self.sort_mut(&mut vec); + let left = vec; + + let mut vec = list.clone(); + vec.drain(..size); + self.sort_mut(&mut vec); + let right = vec; + let merged = self.merge(&left, &right); + + *list = merged; + } + } + + fn num_comp(&self) -> u64 { + self.comparisons + } + + fn num_swap(&self) -> u64 { + self.swaps + } + + fn reset_state(&mut self) { + self.comparisons = 0; + self.swaps = 0; + } +} diff --git a/libsort/src/my_sort.rs b/libsort/src/my_sort.rs new file mode 100644 index 0000000..d8de98b --- /dev/null +++ b/libsort/src/my_sort.rs @@ -0,0 +1,137 @@ +use crate::{merge_sort::MergeSort, CompareResult, Sort}; + +pub struct MySort { + comparisons: u64, + swaps: u64, + merge: MergeSort, +} + +impl MySort { + fn compare(&mut self, a: u64, b: u64) -> CompareResult { + self.comparisons += 1; + if a < b { + CompareResult::LESS + } else if a > b { + CompareResult::GREATER + } else { + CompareResult::EQUAL + } + } + + fn extend_run_left(&mut self, list: &Vec, mut i: usize) -> usize { + use CompareResult::*; + while i > 0 && self.compare(list[i - 1], list[i]) != GREATER { + i -= 1; + } + + i + } + + fn extend_run_right(&mut self, list: &Vec, mut i: usize) -> usize { + use CompareResult::*; + while i < list.len() - 1 && self.compare(list[i], list[i + 1]) != GREATER { + i += 1; + } + + i + } + + fn _mysort(&mut self, list: &mut Vec, low: usize, high: usize, e: usize, s: usize) { + + if e == high || s == low { + return; + } + let mid = low + (high - low) / 2; + + if mid <= e { + self._mysort(list, e + 1, high, e + 1, s); + + let mut left = list.clone(); + left.drain(e + 1..); + left.drain(..low); + let mut right = list.clone(); + right.drain(high + 1..); + right.drain(..=e); + list.copy_from_slice(&self.merge.merge(&left, &right)); + + self.comparisons += self.merge.num_comp(); + self.swaps += self.merge.num_swap(); + } else if mid >= s { + self._mysort(list, low, s - 1, e, s - 1); + + let mut left = list.clone(); + left.drain(s..); + left.drain(..low); + let mut right = list.clone(); + right.drain(high + 1..); + right.drain(..s); + list.copy_from_slice(&self.merge.merge(&left, &right)); + + self.comparisons += self.merge.num_comp(); + self.swaps += self.merge.num_swap(); + } else { + let i = self.extend_run_left(list, low); + let j = self.extend_run_right(list, high); + if i == low && j == high { + return; + } + + if mid - i < j - mid { + self._mysort(list, low, i - 1, e, i - 1); + self._mysort(list, i, high, j, s); + + let mut left = list.clone(); + left.drain(i..); + left.drain(..low); + let mut right = list.clone(); + right.drain(high + 1..); + right.drain(..i); + list.copy_from_slice(&self.merge.merge(&left, &right)); + + self.comparisons += self.merge.num_comp(); + self.swaps += self.merge.num_swap(); + } else { + self._mysort(list, low, j, e, i); + self._mysort(list, j + 1, high, j + 1, s); + + let mut left = list.clone(); + left.drain(j + 1..); + left.drain(..low); + let mut right = list.clone(); + right.drain(high + 1..); + right.drain(..=j); + list.copy_from_slice(&self.merge.merge(&left, &right)); + + self.comparisons += self.merge.num_comp(); + self.swaps += self.merge.num_swap(); + } + } + } +} + +impl Sort for MySort { + fn new(should_print: bool) -> Self { + Self { + comparisons: 0, + swaps: 0, + merge: MergeSort::new(should_print), + } + } + + fn sort_mut(&mut self, list: &mut Vec) { + self._mysort(list, 0, list.len() - 1, 0, list.len() - 1) + } + + fn num_comp(&self) -> u64 { + self.comparisons + } + + fn num_swap(&self) -> u64 { + self.swaps + } + + fn reset_state(&mut self) { + self.comparisons = 0; + self.swaps = 0; + } +}