How to see running output from a Rust function on console? - rust

I have a function in Rust which returns a vector of vectors of the number of combinations possible from a set given a number of digits for which the combinations are needed(nCk).
If the set is [1,2,3] and the number of digits(k) is 2, the output is:
[[1, 2], [1, 3], [2, 3]]
However, if I choose k to be a large number, it takes too much time and prints all of the output at once after it has finished processing.
Is it possible that it keeps giving me running output on the go?
In Java, I have the same thing and it gives me running output.
Here's my function:
fn comb<T>(slice: &[T], k: usize) -> Vec<Vec<T>>
where
T: Copy,
{
if k == 1 {
return slice.iter().map(|x| vec![*x]).collect::<Vec<Vec<T>>>();
}
if k == slice.len() {
return vec![slice.to_vec()];
}
let mut result = comb(&slice[1..], k - 1)
.into_iter()
.map(|x| [&slice[..1], x.as_slice()].concat())
.collect::<Vec<Vec<T>>>();
result.extend(comb(&slice[1..], k));
return result;
}

I solved the problem.
There was no running output because there was no print statement in the function itself, although it was there in the main function.
Adding a print statement in the function itself solved the problem:]
let mut result = comb(&slice[1..], k - 1)
.into_iter()
.map(|x| {
let output = [&slice[..1], x.as_slice()].concat();
println!("{:?}", output);
output
})
.collect::<Vec<Vec<T>>>();
Also, you would need to change the signature a little:
T: Copy + Debug
T would now need to implement Debug as well.

Related

How to compare the value of next element with the current element in an iterator without a loop and for_each?

I have a vector like [1, 2, 4, 3], I want to remove 3 because 3 is smaller than 4.
I want to use the iterator to solve this problem, and do not use the loop or for_each.
The first step I think need to do is vec.into_iter, but I don't know what to do next.
To reformulate, you want to remove any element smaller than the previous element.
Let's write a function to do so. As you want to work exclusively with iterators, therefore in a functional style, we are going to assume the input vector is immutable, so the function should take a slice as input, and return a new Vec:
fn remove_smaller<T: Ord + Copy>(v: &[T]) -> Vec<T> {
v.iter()
.rev()
.collect::<Vec<_>>()
.windows(2)
.filter(|a| a[0] > a[1])
.map(|a| *a[0])
.chain([v[0]])
.rev()
.collect()
}
Let's explain what this function is doing, using vec![1, 2, 4, 3] as sample input.
We first reverse the order of the vector so we can operate on windows looking at the previous value, and collect it into a new vector (needed as windows is implemented for slices only).
&[3, 4, 2, 1]
windows(2) returns an iterator that will yield overlapping pairs of elements of the slice, except the last element, which has no next:
&[3, 4], &[4, 2], &[2, 1]
We then filter with filter(|a| a[0] > a[1]) meaning we only keep entries which are ordered (hence why type of input needs to be Ord):
&[4, 2], &[2, 1]
We then map with map(|a| *a[0]) in order to keep each value, which needs T to be Copy:
4, 2
Now, since we are missing the first element of the input array, we need to add it again, using .chain([v[0]]) giving us:
4, 2, 1
We then reverse the iterator to obtain the output array in correct order:
1, 2, 4
See it in action in the playground.
This is not a very efficient method to achieve the result, as it needs to allocate twice as much memory as the input.
You can use the zip and skip functionality to put together two elements of an array.
Following the footsteps of #sirdarius, Here is how your function can be:
fn remove_smaller<T: Ord + Copy>(v: &[T]) -> Vec<T> {
let mut res = vec![v[0]];
res.extend(
v.iter()
.zip(v.iter().skip(1))
.filter(|(a, b)| a < b)
.map(|(_, b)| *b),
);
res
}
Walk through:
We fist create our result vector and push the first element in it since it is always in the answer vector.
Then we extend our result vector by another iterator which would perform the following:
create a tuple for each element of the array with indices of the same array but one index ahead (v.iter().skip(1)).
we then filter out pairs which meet our ordering and finally, we map the pair to a single value.
There is an iterator only way to do what you wanted in O(1) space.
fn non_decreasing(v: Vec<i32>) -> Vec<i32> {
if v.is_empty() {
return v;
}
let first = v[0];
once(first)
.chain(
v.into_iter()
.skip(1)
.scan(first, |last_max, cur_elem| {
if cur_elem < *last_max {
Some(None)
} else {
*last_max = cur_elem;
Some(Some(cur_elem))
}
})
.flatten(),
)
.collect()
}
This function will not use any extra space (even for the output, on newer rustc versions). It will return a vector that's non-decreasing. That is, each element in the result vector will be >= the previous one.
If you wanted to compare the elements only to the previous element and not the previous largest, then just add the *last_max = cur_elem line to the if branch as well.

How to chain arbitrary number of iterables?

I understand some of the jank involving iterables and arrays, but clearly not enough. I want to take any amount of iterables (vectors, arrays, slices, anything implementing IntoIterator) and provide an expected final size, and get an array (i.e. fixed-size) containing the chained values. To clarify, this is mostly for easy refactoring and function calling, so I want this utility to take ownership of the passed iterables and move all their contents into its output, such that:
let a1: u8 = [1, 2, 3];
let a2: u8 = [4, 5, 6];
let joined = join::<u8, 6>([a1, a2, ...]); // [u8; 6]
I tried implementing something with chain, but couldn't get it to work out. I know I can do this unsafely, but I'd rather avoid that if possible. Is there a way to do what I want?
My best (non-working) attempt:
fn join<T, C: IntoIterator<Item = T>, const N: usize>(iterables: Vec<C>) -> [T; N] {
let mut a = vec![].iter().chain(vec![]);
for iterable in iterables {
a = a.chain(iterable.into_iter());
}
a.collect().try_into().unwrap()
}
With credit to #SvenMarnach for simplifying, this problem is neatly solved like so:
use std::convert::TryInto;
fn join<T: Clone, const N: usize>(iterables: Vec<&[T]>) -> [T; N] {
let slice = iterables.concat();
let length = slice.len();
slice.try_into()
.unwrap_or_else(|_| panic!("joined has length {}, expected {}", length, N))
}
Used like so:
fn main() {
let params1 = [1, 2, 3];
let params2 = [4, 5];
print!("sum: {}", sum_six_numbers(join(vec![&params1, &params2])));
}
fn sum_six_numbers(ns: [u8; 5]) -> u8 {
ns.iter().sum()
}

Retrieve the state in scan() iterator?

To obtain the partial sums of a sequence of integers, I can use scan() on the iterator like this:
let partial: Box<[u32]> =
list
.iter()
.scan(0, |st, elem| {
let ret = *st;
*st += elem;
Some(ret)
})
.collect();
The above code works well, but I'm trying to modify it to give me the total sum as well.
Something like:
let (partial, total): (Box<[u32]>, u32) =
list
.iter()
.scan(0, |st, elem| {
// TODO
})
.collect();
It seems like I would just need to obtain the eventual value of st, and the iterator should already know it's value. However, I can't seem to find a way to retrieve that value, short of doing a second iteration over the whole sequence (e.g. with fold()).
Is there a way to find the partial sums and the total sum in a single pass?
Include the total sum in the scan, but then split off the last value.
use std::iter;
fn main() {
let list = vec![1, 2, 3, 4];
// Add zero at the start to emulate what you had before
let partial: Box<[u32]> = iter::once(0)
.chain(list.iter().scan(0, |st, elem| {
*st += elem;
Some(*st)
}))
.collect();
// unwrap since with the added zero, the slice will always be non-empty
let (total, partial) = partial.split_last().unwrap();
println!("partial sums: {:?}", partial);
println!("total sum: {}", total);
}
(playground)
Or using successors():
fn main() {
use std::iter::successors;
let list = vec![1, 2, 3, 4];
let mut iter = list.iter();
let partial: Vec<_> = successors(Some(0), |n| iter.next().map(|i| n + i)).collect();
// unwrap since with the added zero, the slice will always be non-empty
let (total, partial) = partial.split_last().unwrap();
assert_eq!(partial, &[0, 1, 3, 6]);
assert_eq!(total, &10);
}
(playground)
You must decide what you want to do in the closure.
As it stands in your code, you remember ret = *st which is the accumulator's value before the addition takes place, and you return Some(ret). Thus, the first item you get in the result is currently 0.
If you want the value after the sums, you should just return Some(*st), which is the updated accumulator's value after the addition.

Why can I not use a slice pattern to filter a Window iterator?

I have a vector of numbers and use the windows(2) method to create an iterator that gives me neighbouring pairs. For example, the vector [1, 2, 3] is transformed into [1, 2], [2, 3]. I want to use the find method to find a slice that fulfills a specific condition:
fn step(g: u64) -> Option<(u64, u64)> {
let prime_list: Vec<u64> = vec![2, 3, 5, 7]; //For example
if prime_list.len() < 2 {
return None;
}
let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
//...
None
}
I get an error:
error[E0005]: refutable pattern in function argument: `&&[]` not covered
--> src/lib.rs:6:43
|
6 | let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
| ^^^^^^^^ pattern `&&[]` not covered
I don't know what that error means: the list cannot have less than two elements, for example. Maybe the closure parameter is wrong? I tried to vary it but that didn't change anything. a and b are being properly detected as u64 in my IDE too. What is going on here?
You, the programmer, know that each iterated value will have a length of 2, but how do you know that? You can only tell that from the prose documentation of the function:
Returns an iterator over all contiguous windows of length size. The windows overlap. If the slice is shorter than size, the iterator returns no values.
Nowhere does the compiler know this information. The implementation of Windows only states that the iterated value will be a slice:
impl<'a, T> Iterator for Windows<'a, T> {
type Item = &'a [T];
}
I'd convert the slice into an array reference, discarding any slices that were the wrong length (which you know cannot happen):
use std::convert::TryFrom;
fn step(g: u64) -> Option<(u64, u64)> {
let prime_list: Vec<u64> = vec![2, 3, 5, 7]; // For example
if prime_list.len() < 2 {
return None;
}
let res = prime_list
.windows(2)
.flat_map(<&[u64; 2]>::try_from)
.find(|&&[a, b]| b - a == g)?;
//...
None
}
See also:
How to convert a slice into an array reference?
How can I find a subsequence in a &[u8] slice?
How do I imply the type of the value when there are no type parameters or ascriptions?
Alternatively, you could use an iterator of integers and chunk it up.
See also:
Are there equivalents to slice::chunks/windows for iterators to loop over pairs, triplets etc?
At some point in the future, const generics might be stabilized and allow baking the array length into the function call and the return type.
See also:
Is it possible to control the size of an array using the type parameter of a generic?

What's the best way to compare 2 vectors or strings element by element?

What's the best way to compare 2 vectors or strings element by element in Rust, while being able to do processing on each pair of elements? For example if you wanted to keep count of the number of differing elements. This is what I'm using:
let mut diff_count: i32 = 0i32;
for (x, y) in a.chars().zip(b.chars()) {
if x != y {
diff_count += 1i32;
}
}
Is that the correct way or is there something more canonical?
To get the count of matching elements, I'd probably use filter and count.
fn main() {
let a = "Hello";
let b = "World";
let matching = a.chars().zip(b.chars()).filter(|&(a, b)| a == b).count();
println!("{}", matching);
let a = [1, 2, 3, 4, 5];
let b = [1, 1, 3, 3, 5];
let matching = a.iter().zip(&b).filter(|&(a, b)| a == b).count();
println!("{}", matching);
}
Iterator::zip takes two iterators and produces another iterator of the tuple of each iterator's values.
Iterator::filter takes a reference to the iterator's value and discards any value where the predicate closure returns false. This performs the comparison.
Iterator::count counts the number of elements in the iterator.
Note that Iterator::zip stops iterating when one iterator is exhausted. If you need different behavior, you may also be interested in
Itertools::zip_longest or Itertools::zip_eq.
If you wanted to use #Shepmaster's answer as the basis of an assertion to be used in a unit test, try this:
fn do_vecs_match<T: PartialEq>(a: &Vec<T>, b: &Vec<T>) -> bool {
let matching = a.iter().zip(b.iter()).filter(|&(a, b)| a == b).count();
matching == a.len() && matching == b.len()
}
Of course, be careful when using this on floats! Those pesky NaNs won't compare, and you might want to use a tolerance for comparing the other values. And you might want to make it fancy by telling the index of the first nonmatching value.

Resources