Skip to content

Commit 7399d50

Browse files
committed
Added unstable version of smoothsort
1 parent cb91ae7 commit 7399d50

File tree

3 files changed

+170
-10
lines changed

3 files changed

+170
-10
lines changed

src/bin/leonardo_numbers.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/// Additional private binary to print Leonardo and Fibonnaci numbers
2+
/// Leonardo numbers are then used in smoothsort algorithm
3+
/// This one can be useful in case you need to modify algorithm to use with
4+
/// 32-, 64-, 128-bit and other systems
5+
/// This addition uses usize in case there is mainstream 64-bit system
6+
/// # Usage:
7+
/// ```no_run
8+
/// cargo run leonardo_numbers
9+
/// ```
10+
use std::io;
11+
12+
fn leonardo_generate(mut n0: usize, mut n1: usize, add: usize) ->
13+
impl std::iter::Iterator<Item = usize> {
14+
std::iter::from_fn(move || {
15+
let n = n0;
16+
n0 = n1;
17+
n1 += n + add;
18+
Some(n)
19+
})
20+
}
21+
22+
fn main() {
23+
let mut input = String::new();
24+
io::stdin().read_line(&mut input).expect("Failed to read value");
25+
input = input.to_string().trim().to_string();
26+
match input.parse::<usize>() {
27+
Ok(input) => {calculate_leonardo(input)},
28+
_ => {println!("Input is not a number!"); main();}
29+
}
30+
}
31+
32+
fn calculate_leonardo(num: usize) {
33+
for i in leonardo_generate(1, 1, 1).take(num) {
34+
print!("{}, ", i);
35+
}
36+
println!();
37+
println!("Maximum number: {}", usize::MAX);
38+
}
39+
40+
/*
41+
fn calculate_fibonacci(num: usize) {
42+
for i in leonardo_generic(0, 1, 0).take(num)
43+
}
44+
*/

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub mod quick_sort;
3131
pub mod selection_sort;
3232
pub mod shell_sort;
3333
pub mod slow_sort;
34-
// pub mod smooth_sort;
34+
pub mod smooth_sort;
3535
pub mod stooge_sort;
3636

3737
pub use self::bubble_sort::bubble_sort;
@@ -46,5 +46,5 @@ pub use self::quick_sort::quick_sort;
4646
pub use self::selection_sort::selection_sort;
4747
pub use self::shell_sort::shell_sort;
4848
pub use self::slow_sort::slow_sort;
49-
// pub use self::smooth_sort::smooth_sort;
49+
pub use self::smooth_sort::smooth_sort;
5050
pub use self::stooge_sort::stooge_sort;

src/smooth_sort.rs

Lines changed: 124 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@
77
/// This sorting algorithm transforms the input array into implicit heap data
88
/// structure and then produces the sorted array by repeatedly extracting the
99
/// largest remaining element
10+
/// This algorithm makes use of Leonardo numbers. It's a sequence of numbers
11+
/// defined by:
12+
/// ```no_run
13+
/// L(0) = 1
14+
/// L(1) = 1
15+
/// L(n) = L(n - 1) + L(n - 2) + 1
16+
/// *OR*
17+
/// L(n) = 2 * Fib(n + 1) - 1
18+
/// ```
19+
/// Where *+ 1* is "add" number and "Fib" are Fibonacci numbers
20+
///
21+
/// For 64-bit systems it's possible to use 90 Leonardo numbers placed as a
22+
/// constant array [usize; 90]
1023
///
1124
/// # Examples
1225
/// ```rust
@@ -19,33 +32,136 @@
1932
/// sorting_rs::smooth_sort(&mut strings);
2033
/// assert_eq!(strings, &["cargo", "rustc", "rustup"]);
2134
/// ```
35+
use std::fmt::Debug;
2236

23-
pub fn smooth_sort<T: PartialOrd>(input: &mut [T]) {
37+
const LEO_NUMS: [usize; 90] = [
38+
1, 1, 3, 5, 9, 15, 25, 41, 67, 109, 177, 287, 465, 753, 1219, 1973, 3193,
39+
5167, 8361, 13529, 21891, 35421, 57313, 92735, 150049, 242785, 392835,
40+
635621, 1028457, 1664079, 2692537, 4356617, 7049155, 11405773, 18454929,
41+
29860703, 48315633, 78176337, 126491971, 204668309, 331160281, 535828591,
42+
866988873, 1402817465, 2269806339, 3672623805, 5942430145, 9615053951,
43+
15557484097, 25172538049, 40730022147, 65902560197, 106632582345,
44+
172535142543, 279167724889, 451702867433, 730870592323, 1182573459757,
45+
1913444052081, 3096017511839, 5009461563921, 8105479075761,
46+
13114940639683, 21220419715445, 34335360355129, 55555780070575,
47+
89891140425705, 145446920496281, 235338060921987, 380784981418269,
48+
616123042340257, 996908023758527, 1613031066098785, 2609939089857313,
49+
4222970155956099, 6832909245813413, 11055879401769513, 17888788647582927,
50+
28944668049352441, 46833456696935369, 75778124746287811, 122611581443223181,
51+
198389706189510993, 321001287632734175, 519390993822245169,
52+
840392281454979345, 1359783275277224515, 2200175556732203861,
53+
3559958832009428377, 5760134388741632239,
54+
];
55+
56+
pub fn smooth_sort<T: PartialOrd + Debug>(input: &mut [T])
57+
{
2458
if input.len() < 2 {return;}
2559

26-
unimplemented!("Not yet ready!");
60+
// Init addtitional heap
61+
let input = input;
62+
let in_len = input.len();
63+
let mut heap = Vec::<usize>::new();
64+
65+
for i in 0..in_len {
66+
if heap.len() >= 2 && heap[heap.len() - 2] == heap[heap.len() - 1] + 1 {
67+
heap.pop();
68+
let len_leo = heap.len();
69+
heap[len_leo - 1] += 1;
70+
} else {
71+
if heap.len() >= 1 && heap[heap.len() - 1] == 1 {
72+
heap.push(0);
73+
} else {
74+
heap.push(1);
75+
}
76+
}
77+
restore_heap(input, i, &heap);
78+
}
79+
println!("DEBUG: {:?}", input);
80+
81+
for i in (0..in_len).rev() {
82+
if heap[heap.len() - 1] < 2 {
83+
heap.pop();
84+
} else {
85+
let k = heap.pop().unwrap();
86+
let t = get_child_trees(i, k);
87+
// tr kr tl kl
88+
// 0 1 2 3
89+
heap.push(t[3]);
90+
restore_heap(input, t[2], &heap);
91+
heap.push(t[1]);
92+
restore_heap(input, t[0], &heap);
93+
}
94+
}
95+
println!("DEBUG: {:?}", input);
96+
}
97+
98+
fn restore_heap<T: PartialOrd>(input: &mut [T], index: usize, heap: &Vec<usize>)
99+
{
100+
// Insertion sorting
101+
let mut current = heap.len() - 1;
102+
let mut i = index;
103+
let mut k = heap[current];
104+
105+
while current > 0 {
106+
let j = i - LEO_NUMS[k];
107+
if input[j] > input[i] && (k < 2 || input[j] > input[i - 1] &&
108+
input[j] > input[i - 2]) {
109+
input.swap(i, j);
110+
i = j;
111+
current -= 1;
112+
k = heap[current];
113+
} else {
114+
break;
115+
}
116+
}
117+
while k > 2 {
118+
let t = get_child_trees(i, k);
119+
// tr kr tl kl
120+
// 0 1 2 3
121+
if input[i] < input[t[0]] || input[i] < input[t[2]] {
122+
if input[t[0]] > input[t[2]] {
123+
input.swap(i, t[0]);
124+
i = t[0];
125+
k = t[1];
126+
} else {
127+
input.swap(i, t[2]);
128+
i = t[2];
129+
k = t[3];
130+
}
131+
} else {
132+
break;
133+
}
134+
}
135+
}
136+
137+
fn get_child_trees(i: usize, k: usize) -> [usize; 4] {
138+
let tr = i - 1;
139+
let kr = k - 2;
140+
let tl = tr - LEO_NUMS[kr];
141+
let kl = k - 1;
142+
[tr, kr, tl, kl]
27143
}
28144

29145
#[cfg(test)]
30146
mod tests {
31147
use super::*;
32148

33149
#[test]
34-
fn test_slow() {
35-
let mut vector_in = vec![10, 20, 11, 24];
150+
fn test_smooth() {
151+
let mut vector_in = vec![20, 10, 11, 13];
36152
smooth_sort(&mut vector_in);
37-
debug_assert_eq!(vector_in, vec![10, 11, 20, 24]);
153+
debug_assert_eq!(vector_in, &[10, 11, 13, 20]);
38154
}
39155
#[test]
40-
fn test_slow_empty() {
156+
fn test_smooth_empty() {
41157
let mut vector_in:Vec<i32> = vec![];
42158
smooth_sort(&mut vector_in);
43159
debug_assert_eq!(vector_in, &[]);
44160
}
45161
#[test]
46-
fn test_slow_len1() {
162+
fn test_smooth_len1() {
47163
let mut vector_in = vec![1];
48164
smooth_sort(&mut vector_in);
49-
debug_assert_eq!(vector_in, vec![1]);
165+
debug_assert_eq!(vector_in, &[1]);
50166
}
51167
}

0 commit comments

Comments
 (0)