Skip to content

Commit

Permalink
Added unstable version of smoothsort
Browse files Browse the repository at this point in the history
  • Loading branch information
flakusha committed Jul 19, 2020
1 parent cb91ae7 commit 7399d50
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 10 deletions.
44 changes: 44 additions & 0 deletions src/bin/leonardo_numbers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/// Additional private binary to print Leonardo and Fibonnaci numbers
/// Leonardo numbers are then used in smoothsort algorithm
/// This one can be useful in case you need to modify algorithm to use with
/// 32-, 64-, 128-bit and other systems
/// This addition uses usize in case there is mainstream 64-bit system
/// # Usage:
/// ```no_run
/// cargo run leonardo_numbers
/// ```
use std::io;

fn leonardo_generate(mut n0: usize, mut n1: usize, add: usize) ->
impl std::iter::Iterator<Item = usize> {
std::iter::from_fn(move || {
let n = n0;
n0 = n1;
n1 += n + add;
Some(n)
})
}

fn main() {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Failed to read value");
input = input.to_string().trim().to_string();
match input.parse::<usize>() {
Ok(input) => {calculate_leonardo(input)},
_ => {println!("Input is not a number!"); main();}
}
}

fn calculate_leonardo(num: usize) {
for i in leonardo_generate(1, 1, 1).take(num) {
print!("{}, ", i);
}
println!();
println!("Maximum number: {}", usize::MAX);
}

/*
fn calculate_fibonacci(num: usize) {
for i in leonardo_generic(0, 1, 0).take(num)
}
*/
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub mod quick_sort;
pub mod selection_sort;
pub mod shell_sort;
pub mod slow_sort;
// pub mod smooth_sort;
pub mod smooth_sort;
pub mod stooge_sort;

pub use self::bubble_sort::bubble_sort;
Expand All @@ -46,5 +46,5 @@ pub use self::quick_sort::quick_sort;
pub use self::selection_sort::selection_sort;
pub use self::shell_sort::shell_sort;
pub use self::slow_sort::slow_sort;
// pub use self::smooth_sort::smooth_sort;
pub use self::smooth_sort::smooth_sort;
pub use self::stooge_sort::stooge_sort;
132 changes: 124 additions & 8 deletions src/smooth_sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@
/// This sorting algorithm transforms the input array into implicit heap data
/// structure and then produces the sorted array by repeatedly extracting the
/// largest remaining element
/// This algorithm makes use of Leonardo numbers. It's a sequence of numbers
/// defined by:
/// ```no_run
/// L(0) = 1
/// L(1) = 1
/// L(n) = L(n - 1) + L(n - 2) + 1
/// *OR*
/// L(n) = 2 * Fib(n + 1) - 1
/// ```
/// Where *+ 1* is "add" number and "Fib" are Fibonacci numbers
///
/// For 64-bit systems it's possible to use 90 Leonardo numbers placed as a
/// constant array [usize; 90]
///
/// # Examples
/// ```rust
Expand All @@ -19,33 +32,136 @@
/// sorting_rs::smooth_sort(&mut strings);
/// assert_eq!(strings, &["cargo", "rustc", "rustup"]);
/// ```
use std::fmt::Debug;

pub fn smooth_sort<T: PartialOrd>(input: &mut [T]) {
const LEO_NUMS: [usize; 90] = [
1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193,
5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049, 242785, 392835,
635621, 1028457, 1664079, 2692537, 4356617, 7049155, 11405773, 18454929,
29860703, 48315633, 78176337, 126491971, 204668309, 331160281, 535828591,
866988873, 1402817465, 2269806339, 3672623805, 5942430145, 9615053951,
15557484097, 25172538049, 40730022147, 65902560197, 106632582345,
172535142543, 279167724889, 451702867433, 730870592323, 1182573459757,
1913444052081, 3096017511839, 5009461563921, 8105479075761,
13114940639683, 21220419715445, 34335360355129, 55555780070575,
89891140425705, 145446920496281, 235338060921987, 380784981418269,
616123042340257, 996908023758527, 1613031066098785, 2609939089857313,
4222970155956099, 6832909245813413, 11055879401769513, 17888788647582927,
28944668049352441, 46833456696935369, 75778124746287811, 122611581443223181,
198389706189510993, 321001287632734175, 519390993822245169,
840392281454979345, 1359783275277224515, 2200175556732203861,
3559958832009428377, 5760134388741632239,
];

pub fn smooth_sort<T: PartialOrd + Debug>(input: &mut [T])
{
if input.len() < 2 {return;}

unimplemented!("Not yet ready!");
// Init addtitional heap
let input = input;
let in_len = input.len();
let mut heap = Vec::<usize>::new();

for i in 0..in_len {
if heap.len() >= 2 && heap[heap.len() - 2] == heap[heap.len() - 1] + 1 {
heap.pop();
let len_leo = heap.len();
heap[len_leo - 1] += 1;
} else {
if heap.len() >= 1 && heap[heap.len() - 1] == 1 {
heap.push(0);
} else {
heap.push(1);
}
}
restore_heap(input, i, &heap);
}
println!("DEBUG: {:?}", input);

for i in (0..in_len).rev() {
if heap[heap.len() - 1] < 2 {
heap.pop();
} else {
let k = heap.pop().unwrap();
let t = get_child_trees(i, k);
// tr kr tl kl
// 0 1 2 3
heap.push(t[3]);
restore_heap(input, t[2], &heap);
heap.push(t[1]);
restore_heap(input, t[0], &heap);
}
}
println!("DEBUG: {:?}", input);
}

fn restore_heap<T: PartialOrd>(input: &mut [T], index: usize, heap: &Vec<usize>)
{
// Insertion sorting
let mut current = heap.len() - 1;
let mut i = index;
let mut k = heap[current];

while current > 0 {
let j = i - LEO_NUMS[k];
if input[j] > input[i] && (k < 2 || input[j] > input[i - 1] &&
input[j] > input[i - 2]) {
input.swap(i, j);
i = j;
current -= 1;
k = heap[current];
} else {
break;
}
}
while k > 2 {
let t = get_child_trees(i, k);
// tr kr tl kl
// 0 1 2 3
if input[i] < input[t[0]] || input[i] < input[t[2]] {
if input[t[0]] > input[t[2]] {
input.swap(i, t[0]);
i = t[0];
k = t[1];
} else {
input.swap(i, t[2]);
i = t[2];
k = t[3];
}
} else {
break;
}
}
}

fn get_child_trees(i: usize, k: usize) -> [usize; 4] {
let tr = i - 1;
let kr = k - 2;
let tl = tr - LEO_NUMS[kr];
let kl = k - 1;
[tr, kr, tl, kl]
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_slow() {
let mut vector_in = vec![10, 20, 11, 24];
fn test_smooth() {
let mut vector_in = vec![20, 10, 11, 13];
smooth_sort(&mut vector_in);
debug_assert_eq!(vector_in, vec![10, 11, 20, 24]);
debug_assert_eq!(vector_in, &[10, 11, 13, 20]);
}
#[test]
fn test_slow_empty() {
fn test_smooth_empty() {
let mut vector_in:Vec<i32> = vec![];
smooth_sort(&mut vector_in);
debug_assert_eq!(vector_in, &[]);
}
#[test]
fn test_slow_len1() {
fn test_smooth_len1() {
let mut vector_in = vec![1];
smooth_sort(&mut vector_in);
debug_assert_eq!(vector_in, vec![1]);
debug_assert_eq!(vector_in, &[1]);
}
}

0 comments on commit 7399d50

Please sign in to comment.