Insertion sort algorithm gives overflow error - rust

When trying to run the insertion sort algorithm as shown below in Rust 1.15.
fn main() {
println!("The sorted set is now: {:?}", insertion_sort(vec![5,2,4,6,1,3]));
}
fn insertion_sort(set: Vec<i32>) -> Vec<i32> {
let mut A = set.to_vec();
for j in 1..set.len() {
let key = A[j];
let mut i = j - 1;
while (i >= 0) && (A[i] > key) {
A[i + 1] = A[i];
i = i - 1;
}
A[i + 1] = key;
}
A
}
I get the error:
thread 'main' panicked at 'attempt to subtract with overflow', insertion_sort.rs:12
note: Run with `RUST_BACKTRACE=1` for a backtrace
Why does an overflow happen here and how is the problem alleviated?

The reason is you tried to calculate 0 - 1 in usize type, which is unsigned (nonnegative). This may lead to an error in Rust.
Why usize? Because Rust expects usize for lengths and indices. You can explicitly convert them into/from signed ones e.g. isize.
fn main() {
println!("The sorted set is now: {:?}", insertion_sort(vec![5,2,4,6,1,3]));
}
fn insertion_sort(set: Vec<i32>) -> Vec<i32> {
let mut A = set.to_vec();
for j in 1..set.len() as isize {
let key = A[j as usize];
let mut i = j - 1;
while (i >= 0) && (A[i as usize] > key) {
A[(i + 1) as usize] = A[i as usize];
i = i - 1;
}
A[(i + 1) as usize] = key;
}
A
}
Another solution, which I recommend, is to avoid negative indices at all. In this case you can use i + 1 instead of i like this:
fn main() {
println!("The sorted set is now: {:?}", insertion_sort(vec![5,2,4,6,1,3]));
}
fn insertion_sort(set: Vec<i32>) -> Vec<i32> {
let mut A = set.to_vec();
for j in 1..set.len() {
let key = A[j];
let mut i = j;
while (i > 0) && (A[i - 1] > key) {
A[i] = A[i - 1];
i = i - 1;
}
A[i] = key;
}
A
}

Related

Merge sort code not giving desired output in rust

I was trying to do a merge sort code in rust.but its not giving the desired output.I tried to debug it for a while but sadly i couldnt find where the error is.
Here is one in Rust Playground.Can you please debug it?
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=25eef03b3d421cc2ae70c3c8a1bb69cb
fn main() {
let mut vec: Vec<u32> = vec![5,7,1,1,3,8,4,4,3,2,1,8,4,9];
let len = vec.len();
let left_index: usize = 0;
let right_index: usize = len - 1;
divide(&mut vec, left_index, right_index);
println!("{:?}",vec);
}
fn divide(mut vec: &mut Vec<u32>, left_index: usize, right_index: usize){
if right_index > left_index {
let middle_index = (left_index + right_index)/2;
divide(&mut vec, left_index, middle_index);
divide(&mut vec, middle_index + 1, right_index);
sort_and_merge(&mut vec, left_index, right_index, middle_index)
}
}
fn sort_and_merge(vec: &mut Vec<u32>, left_index: usize, right_index: usize, middle_index: usize){
let mut vec_left: Vec<u32> = vec![];
let mut vec_right: Vec<u32> = vec![];
for i in left_index..= middle_index{
vec_left.push(vec[i]);
}
for i in (middle_index+1)..= right_index{
vec_right.push(vec[i]);
}
let mut i = 0; // i for vec_left
let mut j = 0; // j for vec_right
let mut k = left_index;
while i < (middle_index - left_index + 1) && j < (right_index - middle_index) {
if vec_left[i] > vec_right[j]{
vec[k] = vec_right[j];
j += 1;
k += 1;
}
else{
vec[k] = vec_left[i];
i += 1;
k += 1;
}
}
while i < vec_left.len(){
vec[k] = vec_left[i];
i += 1;
k += 1;
}
while j < vec_right.len(){
vec[k] = vec_left[j];
j += 1;
k += 1;
}
}
Quoting the code in question:
let mut j = 0; // j for vec_right
...
while j < vec_right.len(){
vec[k] = vec_left[j];
j += 1;
k += 1;
}
In the last part, it seems that you'd want to use vec_right[j].

How to swap contents of two indices of a Vec inside a loop?

I'm trying to swap the elements inside a loop.
fn foo(nums: &mut Vec<i32>) {
let mut i: usize = 0;
for (j, n) in nums.iter_mut().enumerate() {
if n != &0 {
// swap nums[i] and nums[j];
i = i + 1;
}
}
}
But I keep getting the same error (along cannot borrow mutable nums multiple times). What am I doing wrong?
Maybe this is not exactly what you want but it may help.
fn main() {
let mut vec = vec![1, 0, 3, 4];
let mut i = 0;
for j in 0..vec.len() {
if vec[j] != 0 {
vec.swap(i, j);
i = i + 1;
}
}
println!("{:?}", vec);
}
Rust Playground

How to create a very large array? [duplicate]

I'm implementing combsort. I'd like to create fixed-size array on the stack, but it shows stack overflow. When I change it to be on the heap (Rust by Example says to allocate in the heap we must use Box), it still shows stack overflow.
fn new_gap(gap: usize) -> usize {
let ngap = ((gap as f64) / 1.3) as usize;
if ngap == 9 || ngap == 10 {
return 11;
}
if ngap < 1 {
return 1;
}
return ngap;
}
fn comb_sort(a: &mut Box<[f64]>) {
// previously: [f64]
let xlen = a.len();
let mut gap = xlen;
let mut swapped: bool;
let mut temp: f64;
loop {
swapped = false;
gap = new_gap(gap);
for i in 0..(xlen - gap) {
if a[i] > a[i + gap] {
swapped = true;
temp = a[i];
a[i] = a[i + gap];
a[i + gap] = temp;
}
}
if !(gap > 1 || swapped) {
break;
}
}
}
const N: usize = 10000000;
fn main() {
let mut arr: Box<[f64]> = Box::new([0.0; N]); // previously: [f64; N] = [0.0; N];
for z in 0..(N) {
arr[z] = (N - z) as f64;
}
comb_sort(&mut arr);
for z in 1..(N) {
if arr[z] < arr[z - 1] {
print!("!")
}
}
}
The output:
thread '<main>' has overflowed its stack
Illegal instruction (core dumped)
Or
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
I know that my stack size is not enough, the same as C++ when creating a non-heap array that is too big inside a function, but this code is using heap but still shows stack overflow. What's really wrong with this code?
As far as I can tell, it seems like that code is still trying to allocate the array on the stack first, and then move it into the box after.
It works for me if I switch to Vec<f64> in place of Box<[f64]> like this:
fn new_gap(gap: usize) -> usize {
let ngap = ((gap as f64) / 1.3) as usize;
if ngap == 9 || ngap == 10 {
return 11;
}
if ngap < 1 {
return 1;
}
return ngap;
}
fn comb_sort(a: &mut [f64]) {
// previously: [f64]
let xlen = a.len();
let mut gap = xlen;
let mut swapped: bool;
let mut temp: f64;
loop {
swapped = false;
gap = new_gap(gap);
for i in 0..(xlen - gap) {
if a[i] > a[i + gap] {
swapped = true;
temp = a[i];
a[i] = a[i + gap];
a[i + gap] = temp;
}
}
if !(gap > 1 || swapped) {
break;
}
}
}
const N: usize = 10000000;
fn main() {
let mut arr: Vec<f64> = std::iter::repeat(0.0).take(N).collect();
//let mut arr: Box<[f64]> = Box::new([0.0; N]); // previously: [f64; N] = [0.0; N];
for z in 0..(N) {
arr[z] = (N - z) as f64;
}
comb_sort(arr.as_mut_slice());
for z in 1..(N) {
if arr[z] < arr[z - 1] {
print!("!")
}
}
}
In the future, the box syntax will be stabilized. When it is, it will support this large allocation, as no function call to Box::new will be needed, thus the array will never be placed on the stack. For example:
#![feature(box_syntax)]
fn main() {
let v = box [0i32; 5_000_000];
println!("{}", v[1_000_000])
}

Thread '<main>' has overflowed its stack when allocating a large array using Box

I'm implementing combsort. I'd like to create fixed-size array on the stack, but it shows stack overflow. When I change it to be on the heap (Rust by Example says to allocate in the heap we must use Box), it still shows stack overflow.
fn new_gap(gap: usize) -> usize {
let ngap = ((gap as f64) / 1.3) as usize;
if ngap == 9 || ngap == 10 {
return 11;
}
if ngap < 1 {
return 1;
}
return ngap;
}
fn comb_sort(a: &mut Box<[f64]>) {
// previously: [f64]
let xlen = a.len();
let mut gap = xlen;
let mut swapped: bool;
let mut temp: f64;
loop {
swapped = false;
gap = new_gap(gap);
for i in 0..(xlen - gap) {
if a[i] > a[i + gap] {
swapped = true;
temp = a[i];
a[i] = a[i + gap];
a[i + gap] = temp;
}
}
if !(gap > 1 || swapped) {
break;
}
}
}
const N: usize = 10000000;
fn main() {
let mut arr: Box<[f64]> = Box::new([0.0; N]); // previously: [f64; N] = [0.0; N];
for z in 0..(N) {
arr[z] = (N - z) as f64;
}
comb_sort(&mut arr);
for z in 1..(N) {
if arr[z] < arr[z - 1] {
print!("!")
}
}
}
The output:
thread '<main>' has overflowed its stack
Illegal instruction (core dumped)
Or
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
I know that my stack size is not enough, the same as C++ when creating a non-heap array that is too big inside a function, but this code is using heap but still shows stack overflow. What's really wrong with this code?
As far as I can tell, it seems like that code is still trying to allocate the array on the stack first, and then move it into the box after.
It works for me if I switch to Vec<f64> in place of Box<[f64]> like this:
fn new_gap(gap: usize) -> usize {
let ngap = ((gap as f64) / 1.3) as usize;
if ngap == 9 || ngap == 10 {
return 11;
}
if ngap < 1 {
return 1;
}
return ngap;
}
fn comb_sort(a: &mut [f64]) {
// previously: [f64]
let xlen = a.len();
let mut gap = xlen;
let mut swapped: bool;
let mut temp: f64;
loop {
swapped = false;
gap = new_gap(gap);
for i in 0..(xlen - gap) {
if a[i] > a[i + gap] {
swapped = true;
temp = a[i];
a[i] = a[i + gap];
a[i + gap] = temp;
}
}
if !(gap > 1 || swapped) {
break;
}
}
}
const N: usize = 10000000;
fn main() {
let mut arr: Vec<f64> = std::iter::repeat(0.0).take(N).collect();
//let mut arr: Box<[f64]> = Box::new([0.0; N]); // previously: [f64; N] = [0.0; N];
for z in 0..(N) {
arr[z] = (N - z) as f64;
}
comb_sort(arr.as_mut_slice());
for z in 1..(N) {
if arr[z] < arr[z - 1] {
print!("!")
}
}
}
In the future, the box syntax will be stabilized. When it is, it will support this large allocation, as no function call to Box::new will be needed, thus the array will never be placed on the stack. For example:
#![feature(box_syntax)]
fn main() {
let v = box [0i32; 5_000_000];
println!("{}", v[1_000_000])
}

Why does rustc say that the variable "totalSplitInv" is out of scope?

I ran the following program past rustc:
#![feature(slicing_syntax)]
fn sortAndCountInv(arr: &mut [i64]) -> i64 {
return sortAndCountInv_(arr, 0, arr.length - 1)
}
fn sortAndCountInv_(arr: &mut [i64], start: i64, finish: i64) {
let lengthOfSubarray = finish - start + 1;
if (lengthOfSubarray == 0) || (lengthOfSubarray == 1) {
return totalSplitInv
}
else {
let half = (start + finish) / 2;
let leftInv = sortAndCountInv_(arr, start, half);
let rightInv = sortAndCountInv_(arr, half + 1, finish);
let splitInv = mergeAndCountSplitInv(arr, start, finish, half);
return leftInv + rightInv + splitInv
}
}
fn mergeAndCountSplitInv(arr: &mut [i64], start: i64, finish: i64, half: i64) -> i64 {
let aux = arr[start..finish + 1];
let divider = half - start;
let mut i = 0;
let mut j = divider + 1;
let mut totalSplitInv = 0;
let lastIndex = aux.length - 1;
for k in range(start, finish + 1) {
if i > divider {
arr[k] = aux[j];
j += 1
} else if j > lastIndex {
arr[k] = aux[i];
i += 1
} else if aux[i] < aux[j] {
arr[k] = aux[i];
i += 1
} else {
arr[k] = aux[j];
j += 1;
totalSplitInv += (divider - i) + 1;
}
}
return totalSplitInv
}
When I try to compile it with rustc v-0.12.0-dev, I get the following scope error:
inversions.rs:9:16: 9:29 error: unresolved name `totalSplitInv`.
inversions.rs:9 return totalSplitInv
Which is to say, in the function mergeAndCountSplitInv, the line return totalSplitInv is invalid because totalSplitInv is out of scope? Why is this the case?
I think the error is pointing to the return totalSplitInv in sortAndCountInv_, not mergeAndCountSplitInv.
fn sortAndCountInv_(arr: &mut [i64], start: i64, finish: i64) {
let lengthOfSubarray = finish - start + 1;
if (lengthOfSubarray == 0) || (lengthOfSubarray == 1) {
return totalSplitInv // here
...

Resources