general cleanup

This commit is contained in:
jacekpoz 2024-05-06 22:55:10 +02:00
parent f0ff9303bd
commit d0de63ca35
Signed by: poz
SSH key fingerprint: SHA256:JyLeVWE4bF3tDnFeUpUaJsPsNlJyBldDGV/dIKSLyN8
32 changed files with 354 additions and 536 deletions

View file

@ -1,6 +1,6 @@
use std::io; use std::io;
use libsort::{hybrid_sort::HybridSort, is_sorted, print_list, Sort}; use libsort::{hybrid_sort::HybridSort, is_sorted, Sort};
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let mut buffer = String::new(); let mut buffer = String::new();
@ -28,8 +28,7 @@ fn main() -> io::Result<()> {
let print = input_list.len() < 40; let print = input_list.len() < 40;
if print { if print {
print!("input: "); println!("input: {:?}", input_list);
print_list(&input_list);
println!(); println!();
} }
@ -39,11 +38,9 @@ fn main() -> io::Result<()> {
if print { if print {
println!(); println!();
print!("input: "); println!("input: {:?}", input_list);
print_list(&input_list);
println!(); println!();
print!("output: "); println!("output: {:?}", list);
print_list(&list);
} }
println!("swaps: {}", hybrid.num_swap()); println!("swaps: {}", hybrid.num_swap());

View file

@ -1,6 +1,6 @@
use std::io; use std::io;
use libsort::{insertion_sort::InsertionSort, is_sorted, print_list, Sort}; use libsort::{insertion_sort::InsertionSort, is_sorted, Sort};
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let mut buffer = String::new(); let mut buffer = String::new();
@ -28,8 +28,7 @@ fn main() -> io::Result<()> {
let print = input_list.len() < 40; let print = input_list.len() < 40;
if print { if print {
print!("input: "); println!("input: {:?}", input_list);
print_list(&input_list);
println!(); println!();
} }
@ -39,11 +38,9 @@ fn main() -> io::Result<()> {
if print { if print {
println!(); println!();
print!("input: "); println!("input: {:?}", input_list);
print_list(&input_list);
println!(); println!();
print!("output: "); println!("output: {:?}", list);
print_list(&list);
} }
println!("swaps: {}", insertion.num_swap()); println!("swaps: {}", insertion.num_swap());

View file

@ -1,6 +1,6 @@
use std::io; use std::io;
use libsort::{is_sorted, print_list, quick_sort::QuickSort, Sort}; use libsort::{is_sorted, quick_sort::QuickSort, Sort};
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let mut buffer = String::new(); let mut buffer = String::new();
@ -28,8 +28,7 @@ fn main() -> io::Result<()> {
let print = input_list.len() < 40; let print = input_list.len() < 40;
if print { if print {
print!("input: "); println!("input: {:?}", input_list);
print_list(&input_list);
println!(); println!();
} }
@ -39,11 +38,9 @@ fn main() -> io::Result<()> {
if print { if print {
println!(); println!();
print!("input: "); println!("input: {:?}", input_list);
print_list(&input_list);
println!(); println!();
print!("output: "); println!("output: {:?}", list);
print_list(&list);
} }
println!("swaps: {}", quick.num_swap()); println!("swaps: {}", quick.num_swap());

View file

@ -1,14 +1,7 @@
mod merge;
mod mergesort;
mod mysort;
use std::{collections::HashMap, env::args, fs::{self, OpenOptions}, io::{self, Write}}; use std::{collections::HashMap, env::args, fs::{self, OpenOptions}, io::{self, Write}};
use libgen::gen_rand; use libgen::gen_rand;
use libsort::{is_sorted, merge_sort::MergeSort, my_sort::MySort, Sort}; use libsort::{is_sorted, merge_sort::MergeSort, my_sort::MySort, Sort};
use mergesort::mergesort;
use crate::mysort::mysort;
fn comp_avg(results_map: &HashMap<u64, Vec<(u64, u64)>>) -> HashMap<u64, f64> { fn comp_avg(results_map: &HashMap<u64, Vec<(u64, u64)>>) -> HashMap<u64, f64> {
results_map.iter() results_map.iter()

View file

@ -1,34 +0,0 @@
use libsort::{compare, CompareResult::*, SortResult};
pub fn merge(list1: &[u64], list2: &[u64], res: &mut SortResult) -> Vec<u64> {
let mut ret = vec![];
let mut i = 0;
let mut j = 0;
while i < list1.len() && j < list2.len() {
if compare(list1[i], list2[j], &mut res.comparisons) == 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
}

View file

@ -1,16 +0,0 @@
use libsort::SortResult;
use crate::merge::merge;
pub fn mergesort(list: &[u64], res: &mut SortResult) -> Vec<u64> {
if list.len() > 1 {
let size = list.len() / 2;
let left = mergesort(&list[0..size], res);
let right = mergesort(&list[size..], res);
let merged = merge(&left, &right, res);
return merged;
}
list.to_vec()
}

View file

@ -1,70 +0,0 @@
use libsort::{compare, CompareResult::*, SortResult};
use crate::merge::merge;
fn extend_run_left(list: &[u64], mut i: usize, res: &mut SortResult) -> usize {
while i > 0 && compare(list[i - 1], list[i], &mut res.comparisons) != GREATER {
i -= 1;
}
i
}
fn extend_run_right(list: &[u64], mut i: usize, res: &mut SortResult) -> usize {
while i < list.len() - 1 && compare(list[i], list[i + 1], &mut res.comparisons) != GREATER {
i += 1;
}
i
}
fn _mysort(list: &mut [u64], low: usize, high: usize, e: usize, s: usize) -> SortResult {
let mut res = SortResult::default();
if e == high || s == low {
return res;
}
let mid = low + (high - low) / 2;
if mid <= e {
let res1 = _mysort(list, e + 1, high, e + 1, s);
list.copy_from_slice(&merge(&list[low..=e], &list[(e + 1)..=high], &mut res));
res.comparisons += res1.comparisons;
res.swaps += res1.swaps;
} else if mid >= s {
let res1 = _mysort(list, low, s - 1, e, s - 1);
list.copy_from_slice(&merge(&list[low..=(s - 1)], &list[s..=high], &mut res));
res.comparisons += res1.comparisons;
res.swaps += res1.swaps;
} else {
let i = extend_run_left(list, low, &mut res);
let j = extend_run_right(list, high, &mut res);
if i == low && j == high {
return res;
}
if mid - i < j - mid {
let res1 = _mysort(list, low, i - 1, e, i - 1);
let res2 = _mysort(list, i, high, j, s);
list.copy_from_slice(&merge(&list[low..=(i - 1)], &list[i..=high], &mut res));
res.comparisons += res1.comparisons + res2.comparisons;
res.swaps += res1.swaps + res2.swaps;
} else {
let res1 = _mysort(list, low, j, e, i);
let res2 = _mysort(list, j + 1, high, j + 1, s);
list.copy_from_slice(&merge(&list[low..=j], &list[(j + 1)..=high], &mut res));
res.comparisons += res1.comparisons + res2.comparisons;
res.swaps += res1.swaps + res2.swaps;
}
}
res
}
pub fn mysort(list: &mut [u64]) -> SortResult {
_mysort(list, 0, list.len() - 1, 0, list.len() - 1)
}

View file

@ -1,82 +0,0 @@
# This file is automatically @generated by Cargo.
# 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 = "gen_asc"
version = "0.1.0"
dependencies = [
"libgen",
]
[[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 = "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"

View file

@ -1,7 +0,0 @@
[package]
name = "gen_asc"
version = "0.1.0"
edition = "2021"
[dependencies]
libgen = { path = "../libgen" }

View file

@ -1,19 +0,0 @@
use std::{env::args, io};
use libgen::gen_asc;
fn main() -> io::Result<()> {
let amount = args().nth(1)
.expect(format!("usage: {} <amount>", args().nth(0).unwrap()).as_str())
.parse::<u64>()
.expect("amount must be u64");
println!("{}", amount);
gen_asc(amount)
.iter()
.for_each(|x| println!("{}", x));
Ok(())
}

View file

@ -1,7 +0,0 @@
[package]
name = "gen_desc"
version = "0.1.0"
edition = "2021"
[dependencies]
libgen = { path = "../libgen" }

View file

@ -1,19 +0,0 @@
use std::{env::args, io};
use libgen::gen_desc;
fn main() -> io::Result<()> {
let amount = args().nth(1)
.expect(format!("usage: {} <amount>", args().nth(0).unwrap()).as_str())
.parse::<u64>()
.expect("amount must be u64");
println!("{}", amount);
gen_desc(amount)
.iter()
.for_each(|x| println!("{}", x));
Ok(())
}

View file

@ -17,9 +17,9 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.14" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@ -28,9 +28,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.154"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
[[package]] [[package]]
name = "libgen" name = "libgen"

View file

@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
libgen = { path = "../libgen" } libgen = { path = "../../libgen" }

View file

@ -1,15 +1,26 @@
use std::{env::args, io}; use std::{env::args, io, process::exit};
use libgen::gen_rand; use libgen::gen_rand;
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let amount = args().nth(1) let amount = args().nth(1)
.expect(format!("usage: {} <amount>", args().nth(0).unwrap()).as_str()) .expect(format!("usage: {} <amount> <order_statistic>", args().nth(0).unwrap()).as_str())
.parse::<u64>() .parse::<u64>()
.expect("amount must be u64"); .expect("amount must be u64");
let order_statistic = args().nth(2)
.expect(format!("usage: {} <amount> <order_statistic>", args().nth(0).unwrap()).as_str())
.parse::<u64>()
.expect("order statistic must be u64");
if !(1..=amount).contains(&order_statistic) {
eprintln!("order statistic must be in range [1..{}]", amount);
exit(1);
}
println!("{}", amount); println!("{}", amount);
println!("{}", order_statistic);
gen_rand(amount) gen_rand(amount)
.iter() .iter()

75
lab3/libgen/Cargo.lock generated
View file

@ -1,75 +0,0 @@
# This file is automatically @generated by Cargo.
# 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 = "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"

View file

@ -1,36 +0,0 @@
use rand::Rng;
pub fn gen_rand(amount: u64) -> Vec<u64> {
(1..=amount)
.map(|_| rand::thread_rng().gen_range(0..(2 * amount)))
.collect()
}
pub fn gen_desc(amount: u64) -> Vec<u64> {
let mut ret = vec![];
let mut last = rand::thread_rng().gen_range((amount)..(2 * amount));
ret.push(last);
for i in 1..amount {
let current = rand::thread_rng().gen_range((amount - i)..(last));
ret.push(current);
last = current;
}
ret
}
pub fn gen_asc(amount: u64) -> Vec<u64> {
let mut ret = vec![];
let mut last = -1;
for i in 1..=amount {
let current = rand::thread_rng().gen_range((last + 1)..=(2 * amount - (amount - i)) as i64);
ret.push(current as u64);
last = current;
}
ret
}

View file

@ -1,99 +0,0 @@
use rand::{thread_rng, Rng};
pub fn insertion_sort_mut(list: &mut [u64]) {
for i in 1..list.len() {
let mut j = i as usize;
while j > 0 && list[j - 1] > list[j] {
list.swap(j - 1, j);
j -= 1;
}
}
}
pub fn insertion_sort(list: &[u64]) -> Vec<u64> {
let mut clone = Vec::from(list);
insertion_sort_mut(&mut clone);
clone
}
fn partition(arr: &mut [u64], lo: usize, hi: usize, pivot: u64) -> usize {
let mut pivot_index = lo;
for i in lo..=hi {
if arr[i] == pivot {
pivot_index = i;
break;
}
}
if pivot_index != lo {
arr.swap(pivot_index, lo);
pivot_index = lo;
}
let mut j = lo;
for i in (lo + 1)..=hi {
if arr[pivot_index] > arr[i] {
j += 1;
arr.swap(j, i);
}
}
arr.swap(j, lo);
j
}
pub fn rand_partition(arr: &mut [u64], lo: usize, hi: usize) -> usize {
let pivot = thread_rng().gen_range(lo..hi);
partition(arr, lo, hi, arr[pivot])
}
fn _rand_select(arr: &mut [u64], lo: usize, hi: usize, k: usize) -> (usize, u64) {
if lo == hi {
return (lo, arr[lo]);
}
let r = rand_partition(arr, lo, hi);
let i = r - lo + 1;
if k == i {
return (r, arr[r]);
} else if k < i {
return _rand_select(arr, lo, r - 1, k);
} else {
return _rand_select(arr, r + 1, hi, k - i);
}
}
pub fn rand_select(arr: &mut [u64], k: usize) -> (usize, u64) {
_rand_select(arr, 0, arr.len() - 1, k)
}
fn _select(arr: &mut [u64], lo: usize, hi: usize, k: usize) -> (usize, u64) {
if lo == hi {
return (lo, arr[lo]);
}
let mut medians: Vec<u64> = vec![];
let mut chunks = arr.chunks(5)
.collect::<Vec<_>>();
for chunk in chunks.iter_mut() {
let chunk = insertion_sort(chunk);
medians.push(chunk[chunk.len() / 2]);
}
let n = hi - lo;
let (_, pivot) = _select(&mut medians, 0, n.div_ceil(5) - 1, (n.div_ceil(5) - 1).div_ceil(2));
let r = partition(arr, lo, hi, pivot);
let i = r - lo + 1;
if i == k {
return (r, arr[r]);
} else if i < k {
return _select(arr, r + 1, hi, k - i);
} else {
return _select(arr, lo, r - 1, k);
}
}
pub fn select(arr: &mut [u64], k: usize) -> (usize, u64) {
_select(arr, 0, arr.len() - 1, k)
}

View file

@ -1,20 +0,0 @@
use libsort::{select, rand_select};
fn main() {
let arr = [3, 28, 9, 2, 4, 42, 23, 123, 24, 12, 43, 287, 723, 61];
print!("select: ");
for pos in 1..=arr.len() {
// println!("input: {:?}", arr);
// println!("positional statistic: {}", pos);
// println!("select: {:?}", select(&mut arr.clone(), pos).1);
// println!("rand_select: {:?}", rand_select(&mut arr.clone(), pos).1);
print!("{} ", select(&mut arr.clone(), pos).1);
}
print!("\n");
print!("rand_select: ");
for pos in 1..=arr.len() {
print!("{} ", rand_select(&mut arr.clone(), pos).1);
}
print!("\n");
}

View file

@ -1,7 +1,6 @@
[package] [package]
name = "libgen" name = "rand_select"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
rand = "0.8.5"

View file

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

View file

@ -8,18 +8,11 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "gen_desc"
version = "0.1.0"
dependencies = [
"libgen",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.14" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
@ -28,17 +21,22 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.154"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
[[package]] [[package]]
name = "libgen" name = "libselect"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"libsort",
"rand", "rand",
] ]
[[package]]
name = "libsort"
version = "0.1.0"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"
@ -75,6 +73,14 @@ dependencies = [
"getrandom", "getrandom",
] ]
[[package]]
name = "select"
version = "0.1.0"
dependencies = [
"libselect",
"libsort",
]
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"

8
lab3/select/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "select"
version = "0.1.0"
edition = "2021"
[dependencies]
libselect = { path = "../../libselect" }
libsort = { path = "../../libsort" }

58
lab3/select/src/main.rs Normal file
View file

@ -0,0 +1,58 @@
use std::{io, process::exit};
use libselect::{normal_select::NormalSelect, Select};
use libsort::{insertion_sort::InsertionSort, quick_sort::QuickSort, Sort};
fn main() -> io::Result<()> {
let mut buffer = String::new();
let stdin = io::stdin();
stdin.read_line(&mut buffer)?;
let list_len = buffer.trim().parse::<u64>().expect("array length has to be u64");
buffer.clear();
stdin.read_line(&mut buffer)?;
let order_statistic = buffer.trim().parse::<usize>().expect("order statistic has to be usize");
buffer.clear();
if !(1..=list_len as usize).contains(&order_statistic) {
eprintln!("order statistic must be in range [1..{}]", list_len);
exit(1);
}
let mut list: Vec<u64> = vec![];
for i in 0..list_len {
stdin.read_line(&mut buffer)?;
list.push(
buffer.trim().parse::<u64>()
.expect(format!("element {} has to be u64", i).as_str())
);
buffer.clear();
}
let input_list: Vec<u64> = list.clone();
let print = input_list.len() <= 50;
let mut normal = NormalSelect::new(print);
let result = normal.select_mut(&mut list, order_statistic);
if print {
println!();
println!("start state: {:?}", input_list);
println!("end state: {:?}", list);
let mut insertion = InsertionSort::new(false);
println!("sorted array: {:?}", insertion.sort(&input_list));
println!("{} order statistic: {}", order_statistic, result);
}
println!("swaps: {}", normal.num_swap());
println!("comparisons: {}", normal.num_comp());
Ok(())
}

View file

@ -26,12 +26,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
[[package]] [[package]]
name = "libsort" name = "libselect"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"libsort",
"rand", "rand",
] ]
[[package]]
name = "libsort"
version = "0.1.0"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"

View file

@ -1,7 +1,8 @@
[package] [package]
name = "libsort" name = "libselect"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
rand = "0.8.5" rand = "0.8.5"
libsort = { path = "../libsort" }

19
libselect/src/lib.rs Normal file
View file

@ -0,0 +1,19 @@
pub mod normal_select;
pub mod randomized_select;
pub trait Select {
fn new(should_print: bool) -> Self;
fn select_mut(&mut self, list: &mut Vec<u64>, order_statistic: usize) -> u64;
fn select(&mut self, list: &Vec<u64>, order_statistic: usize) -> u64 {
let mut list = list.clone();
self.select_mut(&mut list, order_statistic)
}
fn num_comp(&self) -> u64;
fn num_swap(&self) -> u64;
fn reset_state(&mut self);
}
#[derive(PartialEq)]
pub enum CompareResult {
LESS, EQUAL, GREATER
}

View file

@ -0,0 +1,112 @@
use libsort::{insertion_sort::InsertionSort, Sort};
use crate::{CompareResult, Select};
pub struct NormalSelect {
comparisons: u64,
swaps: u64,
should_print: bool,
insertion: InsertionSort,
}
impl NormalSelect {
fn swap(&mut self, list: &mut Vec<u64>, 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
}
}
pub fn partition(&mut self, list: &mut Vec<u64>, lo: usize, hi: usize, mut pivot_index: usize) -> usize {
if pivot_index != lo {
self.swap(list, pivot_index, lo);
pivot_index = lo;
}
let mut j = lo;
for i in (lo + 1)..=hi {
use CompareResult::*;
if self.compare(list[pivot_index],list[i]) == GREATER {
j += 1;
self.swap(list, j, i);
}
}
self.swap(list, j, lo);
j
}
fn _select(&mut self, list: &mut Vec<u64>, lo: usize, hi: usize, k: usize) -> (usize, u64) {
if lo == hi {
return (lo, list[lo]);
}
if self.should_print { println!("list: {:?}; lo: {lo}; hi: {hi}", list); }
let mut medians: Vec<u64> = vec![];
let mut chunks = list.chunks(5)
.collect::<Vec<_>>();
for chunk in chunks.iter_mut() {
let chunk = self.insertion.sort(&chunk.to_vec());
medians.push(chunk[chunk.len() / 2]);
}
if self.should_print { println!("medians: {:?}", medians); }
self.comparisons += self.insertion.num_comp();
self.swaps += self.insertion.num_swap();
self.insertion.reset_state();
let n = hi - lo;
let (pivot, _) = self._select(&mut medians, 0, n.div_ceil(5) - 1, (n.div_ceil(5) - 1).div_ceil(2));
if self.should_print { println!("pivot: {pivot}"); }
let r = self.partition(list, lo, hi, pivot);
if self.should_print { println!("r: {r}"); }
let i = r - lo + 1;
if i == k {
return (r, list[r]);
} else if i < k {
return self._select(list, r + 1, hi, k - i);
} else {
return self._select(list, lo, r - 1, k);
}
}
}
impl Select for NormalSelect {
fn new(should_print: bool) -> Self {
Self {
comparisons: 0,
swaps: 0,
should_print,
insertion: InsertionSort::new(false),
}
}
fn select_mut(&mut self, list: &mut Vec<u64>, order_statistic: usize) -> u64 {
self._select(list, 0, list.len() - 1, order_statistic).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;
self.insertion.reset_state();
}
}

View file

@ -0,0 +1,85 @@
use rand::{thread_rng, Rng};
use crate::{normal_select::NormalSelect, CompareResult, Select};
pub struct RandomizedSelect {
comparisons: u64,
swaps: u64,
should_print: bool,
normal: NormalSelect,
}
impl RandomizedSelect {
fn swap(&mut self, list: &mut Vec<u64>, 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 rand_partition(&mut self, list: &mut Vec<u64>, lo: usize, hi: usize) -> usize {
let pivot = thread_rng().gen_range(lo..hi);
if self.should_print { println!("pivot: {pivot}"); }
self.normal.partition(list, lo, hi, pivot)
}
fn _select(&mut self, list: &mut Vec<u64>, lo: usize, hi: usize, k: usize) -> (usize, u64) {
if lo == hi {
return (lo, list[lo]);
}
if self.should_print { println!("list: {:?}; lo: {lo}; hi: {hi}", list); }
let r = self.rand_partition(list, lo, hi);
if self.should_print { println!("r: {r}"); }
self.comparisons += self.normal.num_comp();
self.swaps += self.normal.num_swap();
self.normal.reset_state();
let i = r - lo + 1;
if k == i {
return (r, list[r]);
} else if k < i {
return self._select(list, lo, r - 1, k);
} else {
return self._select(list, r + 1, hi, k - i);
}
}
}
impl Select for RandomizedSelect {
fn new(should_print: bool) -> Self {
Self {
comparisons: 0,
swaps: 0,
should_print,
normal: NormalSelect::new(should_print),
}
}
fn select_mut(&mut self, list: &mut Vec<u64>, order_statistic: usize) -> u64 {
self._select(list, 0, list.len() - 1, order_statistic).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;
self.normal.reset_state();
}
}

View file

@ -32,14 +32,18 @@ impl Sort for HybridSort {
if self.should_print { println!("<hybrid_insertion>"); } if self.should_print { println!("<hybrid_insertion>"); }
self.insertion.sort_mut(list); self.insertion.sort_mut(list);
if self.should_print { println!("</hybrid_insertion>"); } if self.should_print { println!("</hybrid_insertion>"); }
self.comparisons += self.insertion.num_comp(); self.comparisons += self.insertion.num_comp();
self.swaps += self.insertion.num_swap(); self.swaps += self.insertion.num_swap();
self.insertion.reset_state();
return; return;
} }
let pivot = self.quick.lomuto_partition(list); let pivot = self.quick.lomuto_partition(list);
self.comparisons += self.quick.num_comp(); self.comparisons += self.quick.num_comp();
self.swaps += self.quick.num_swap(); self.swaps += self.quick.num_swap();
self.quick.reset_state();
if self.should_print { if self.should_print {
println!("<hybrid_quick>"); println!("<hybrid_quick>");
@ -64,5 +68,7 @@ impl Sort for HybridSort {
fn reset_state(&mut self) { fn reset_state(&mut self) {
self.comparisons = 0; self.comparisons = 0;
self.swaps = 0; self.swaps = 0;
self.insertion.reset_state();
self.quick.reset_state();
} }
} }

View file

@ -51,6 +51,7 @@ impl MySort {
self.comparisons += self.merge.num_comp(); self.comparisons += self.merge.num_comp();
self.swaps += self.merge.num_swap(); self.swaps += self.merge.num_swap();
self.merge.reset_state();
} else if mid >= s { } else if mid >= s {
self._mysort(list, low, s - 1, e, s - 1); self._mysort(list, low, s - 1, e, s - 1);
@ -59,6 +60,7 @@ impl MySort {
self.comparisons += self.merge.num_comp(); self.comparisons += self.merge.num_comp();
self.swaps += self.merge.num_swap(); self.swaps += self.merge.num_swap();
self.merge.reset_state();
} else { } else {
let i = self.extend_run_left(list, low); let i = self.extend_run_left(list, low);
let j = self.extend_run_right(list, high); let j = self.extend_run_right(list, high);
@ -75,6 +77,7 @@ impl MySort {
self.comparisons += self.merge.num_comp(); self.comparisons += self.merge.num_comp();
self.swaps += self.merge.num_swap(); self.swaps += self.merge.num_swap();
self.merge.reset_state();
} else { } else {
self._mysort(list, low, j, e, i); self._mysort(list, low, j, e, i);
self._mysort(list, j + 1, high, j + 1, s); self._mysort(list, j + 1, high, j + 1, s);
@ -84,6 +87,7 @@ impl MySort {
self.comparisons += self.merge.num_comp(); self.comparisons += self.merge.num_comp();
self.swaps += self.merge.num_swap(); self.swaps += self.merge.num_swap();
self.merge.reset_state();
} }
} }
} }
@ -113,5 +117,6 @@ impl Sort for MySort {
fn reset_state(&mut self) { fn reset_state(&mut self) {
self.comparisons = 0; self.comparisons = 0;
self.swaps = 0; self.swaps = 0;
self.merge.reset_state();
} }
} }

View file

@ -37,7 +37,7 @@ impl QuickSort {
} }
if swap != pivot { if swap != pivot {
list.swap(swap, pivot); self.swap(list, swap, pivot);
} }
swap as u64 swap as u64