From 2b3c7f70d4d807b8ddecf1b75e63f84b6d5e2dc7 Mon Sep 17 00:00:00 2001 From: jacekpoz Date: Tue, 9 Apr 2024 23:56:42 +0200 Subject: [PATCH] some lab2/zad4 work (still broken) --- lab2/zad4/Cargo.lock | 73 ++++++++++++++++ lab2/zad4/Cargo.toml | 1 + lab2/zad4/src/main.rs | 190 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 257 insertions(+), 7 deletions(-) diff --git a/lab2/zad4/Cargo.lock b/lab2/zad4/Cargo.lock index 4ebb38d..3215cc1 100644 --- a/lab2/zad4/Cargo.lock +++ b/lab2/zad4/Cargo.lock @@ -2,13 +2,86 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libgen" +version = "0.1.0" +dependencies = [ + "rand", +] + [[package]] name = "libsort" version = "0.1.0" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "zad4" version = "0.1.0" dependencies = [ + "libgen", "libsort", ] diff --git a/lab2/zad4/Cargo.toml b/lab2/zad4/Cargo.toml index 8fe5979..fb903fa 100644 --- a/lab2/zad4/Cargo.toml +++ b/lab2/zad4/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] +libgen = { path = "../zad1/libgen" } libsort = { path = "../zad1/libsort" } diff --git a/lab2/zad4/src/main.rs b/lab2/zad4/src/main.rs index 8088ce6..b648dcb 100644 --- a/lab2/zad4/src/main.rs +++ b/lab2/zad4/src/main.rs @@ -1,4 +1,7 @@ -use libsort::{quick_sort, SortResult}; +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}; #[derive(PartialEq)] enum CompareResult { @@ -24,6 +27,10 @@ fn swap(list: &mut [u64], i: usize, j: usize, swaps: &mut u64) { use CompareResult::*; fn dual_pivot_partition(list: &mut [u64], res: &mut SortResult) -> (usize, usize) { + if list.len() < 2 { + return (0, 0); + } + let mut comps = 0; let mut swaps = 0; if compare(list[0], list[list.len() - 1], &mut comps) == GREATER { @@ -34,7 +41,7 @@ fn dual_pivot_partition(list: &mut [u64], res: &mut SortResult) -> (usize, usize let mut g = list.len() - 2; let mut k = l; let p = list[0]; - let q = list[list.len()]; + let q = list[list.len() - 1]; while k <= g { if compare(list[k], p, &mut comps) == LESS { @@ -66,13 +73,23 @@ fn dual_pivot_partition(list: &mut [u64], res: &mut SortResult) -> (usize, usize (l, g) } -fn dual_pivot_quick_sort(list: &mut [u64]) -> SortResult { +fn dual_pivot_quick_sort(list: &mut [u64], print: bool) -> SortResult { let mut res = SortResult::default(); + if list.len() == 0 { + return res; + } + let (lp, rp) = dual_pivot_partition(list, &mut res); - let res1 = dual_pivot_quick_sort(&mut list[..(lp - 1)]); - let res2 = dual_pivot_quick_sort(&mut list[(lp + 1)..=(rp - 1)]); - let res3 = dual_pivot_quick_sort(&mut list[(rp + 1)..]); + + if print { + println!("left pivot = {lp}; right pivot = {rp}:"); + print_list(&list); + } + + let res1 = 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; @@ -80,5 +97,164 @@ fn dual_pivot_quick_sort(list: &mut [u64]) -> SortResult { res } -fn main() { +fn comp_avg(results_map: &HashMap>) -> HashMap { + results_map.iter() + .map(|(i, results)| + (*i, (results.iter() + .map(|res| res.comparisons) + .sum::() as f64 / results.len() as f64))) + .collect() +} + +fn swap_avg(results_map: &HashMap>) -> HashMap { + results_map.iter() + .map(|(i, results)| + (*i, (results.iter() + .map(|res| res.swaps) + .sum::() as f64 / results.len() as f64))) + .collect() +} + +fn sort_stdin() -> io::Result<()> { + let mut buffer = String::new(); + + let stdin = io::stdin(); + + stdin.read_line(&mut buffer)?; + + let list_len = buffer.trim().parse::().expect("array length has to be u64"); + buffer.clear(); + + let mut list: Vec = vec![]; + + for i in 0..list_len { + stdin.read_line(&mut buffer)?; + list.push( + buffer.trim().parse::() + .expect(format!("element {} has to be u64", i).as_str()) + ); + buffer.clear(); + } + + let input_list: Vec = list.clone(); + + let print = input_list.len() < 40; + + if print { + print!("input: "); + print_list(&input_list); + println!(); + } + + let res = dual_pivot_quick_sort(&mut list, print); + + if print { + println!(); + print!("input: "); + print_list(&input_list); + println!(); + print!("output: "); + print_list(&list); + } + + println!("swaps: {}", res.swaps); + println!("comparisons: {}", res.comparisons); + + println!("is sorted: {}", is_sorted(&list)); + + Ok(()) +} + +fn main() -> io::Result<()> { + if args().len() == 1 { + return sort_stdin(); + } + + let k = args().nth(1) + .expect(format!("usage: {} ", args().nth(0).unwrap()).as_str()) + .parse::() + .expect("k must be u64"); + + 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![]); + 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)); + } + } + + 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![]); + for _ in 0..k { + quick_results_large.get_mut(&n).unwrap().push(quick_sort(&mut gen_rand(n), false)); + } + } + + let quick_comp_averages_small = comp_avg(&quick_results_small); + + let quick_swap_averages_small = swap_avg(&quick_results_small); + + let quick_comp_averages_large = comp_avg(&quick_results_large); + + let quick_swap_averages_large = swap_avg(&quick_results_large); + + let dual_pivot_comp_averages_small = comp_avg(&dual_pivot_results_small); + + let dual_pivot_swap_averages_small = swap_avg(&dual_pivot_results_small); + + let dual_pivot_comp_averages_large = comp_avg(&dual_pivot_results_large); + + let dual_pivot_swap_averages_large = swap_avg(&dual_pivot_results_large); + + _ = fs::create_dir_all(format!("./results/k{k}")); + + _ = fs::remove_file(format!("./results/k{k}/small")); + + let mut small = OpenOptions::new() + .create(true) + .append(true) + .open(format!("./results/k{k}/small"))?; + + for n in (10..=50).step_by(10) { + writeln!(small, "{n} {} {} {} {} {} {} {} {}", + quick_comp_averages_small[&n], + quick_swap_averages_small[&n], + dual_pivot_comp_averages_small[&n], + dual_pivot_swap_averages_small[&n], + quick_comp_averages_small[&n] / n as f64, + quick_swap_averages_small[&n] / n as f64, + dual_pivot_comp_averages_small[&n] / n as f64, + dual_pivot_swap_averages_small[&n] / n as f64, + )?; + } + + _ = fs::remove_file(format!("./results/k{k}/large")); + + let mut large = OpenOptions::new() + .create(true) + .append(true) + .open(format!("./results/k{k}/large"))?; + + for n in (1000..=50000).step_by(1000) { + writeln!(large, "{n} {} {} {} {} {} {} {} {}", + quick_comp_averages_large[&n], + quick_swap_averages_large[&n], + dual_pivot_comp_averages_large[&n], + dual_pivot_swap_averages_large[&n], + quick_comp_averages_large[&n] / n as f64, + quick_swap_averages_large[&n] / n as f64, + dual_pivot_comp_averages_large[&n] / n as f64, + dual_pivot_swap_averages_large[&n] / n as f64, + )?; + } + + Ok(()) }