How to interlace an iterator with itself from the end? - rust

I have an iterator in the form 0..=63, i.e.
0 1 2 3 4 ... 59 60 61 62 63.
Its .count() is 64.
How would I get the following iterator:
0 63 1 62 2 61 3 60 4 59 ...
(of course independent of the items present in the iterator), preferably without cloning?
The .count() should stay the same, as only the order of items should change.
I've looked in the standard library and couldn't find it, same in the itertools crate.

Here's one way using only the standard library. It requires a DoubleEndedIterator and will skip the last item for odd sized iterators:
fn main() {
let mut range = (0..=63).into_iter();
let iter = std::iter::from_fn(|| Some([range.next()?, range.next_back()?])).flatten();
dbg!(iter.collect::<Vec<_>>());
}
Output:
[src/main.rs:4] iter.collect::<Vec<_>>() = [
0,
63,
1,
62,
2,
61,
3,
...
30,
33,
31,
32,
]
Playground
#Finomnis has posted a solution in case your input has an odd number of items.

This solution works for all iterators that implement DoubleEndedIterator:
Note that this solution is guaranteed to return all items, regardless of whether the iterator contains an even or odd number of them.
fn selfinterlace<Iter>(mut iter: Iter) -> impl Iterator<Item = Iter::Item>
where
Iter: DoubleEndedIterator,
{
let mut from_front = false;
std::iter::from_fn(move || {
from_front = !from_front;
if from_front {
iter.next()
} else {
iter.next_back()
}
})
}
fn main() {
let range = (0..=8).into_iter();
let iter = selfinterlace(range);
println!("{:?}", iter.collect::<Vec<_>>());
}
[0, 8, 1, 7, 2, 6, 3, 5, 4]
The idea is that you store whether the next item should be from the front or the back, and then flip that in every iteration.
from_fn can take FnMut, meaning, it can take closures that store internal state. The internal state in this closure consists of the variables iter and from_front, which get moved into the closure through the move || keyword.

You could use itertools::interleave to interleave forward and reverse iterators.
RangeInclusive<i32> doesn't implement ExactSizedIterator so there's no .len() function. We have to calculate it ourselves.
If the range has an odd length the extra item will show up in the forward half thanks to (len + 1).
let range = 0..=63;
let len = range.end() - range.start() + 1;
let iter = itertools::interleave(
range.clone().take((len + 1) / 2),
range.clone().rev().take(len / 2),
);
Playground

Related

Doing more than 1 thing in a iter().map()

I would like to use a map to create a new vector, but at the same time, do other things inside that map. I'm working on Advent of Code 2021, day 6 part 1.
This code loops through a vector and decrements all the values by one. If the value is at 0, then it resets that position to 6 and adds an 8 to the end of the vector.
fn run_growth_simulation(mut state: Vec<u8>, days: i32) -> usize {
for _day in 0..days {
let mut new_fish = 0;
state.iter_mut().map(|x| match x {
num: u8 # 1..=8 => {num - 1},
0 => {new_fish += 1; 6},
_ => unreachable!()
})
for _fish in 0..new_fish {
state.push(8);
}
}
state.iter().count() as usize
}
How do I return the right item from the closure?
I would mutate the value in the iterator directly and not build a new array, because of that use for_each instead of map (or preferable directly a for loop).
Then inside the match statement mutate the value:
state.iter_mut().for_each(|x| match x {
//: u8 removed because it gave me an syntax error
// mutate the number directly (we have to use `num` because x was moved)
num # 1..=8 => {*num -= 1;},
// mutate the number
0 => {new_fish += 1; *x = 6;},
_ => unreachable!()
});
A slightly different approach would be to count the 0s in the vector, remove them, subtract each value by 1 and add the new fish
As a complement to the answer stating that for_each() is preferable to map() here (since we don't consume what map() emits), below is a simpler example trying to illustrate the problem (and why the borrow-checker is right when it forbids such attempts).
In both cases (test1() and test2()) we are iterating over a vector while we are extending it (this is what was intended in the question).
In test1() the iterator considers the storage for the values once for all when it is created.
For all the subsequent iterations, it will refer to this initial storage, thus this storage must not move elsewhere in memory in the meantime.
That's why the iterator borrows the vector (mutably or not, this is not important here).
However, during these iterations we try to append new values to this vector: this may move the storage (for reallocation purpose) and fortunately this requires a mutable borrow of the vector (then it's rejected).
In test2() we avoid keeping a reference to the initial storage, and use a counter instead.
This works, but this is suboptimal since at each iteration this index operation ([]) needs to check the bounds.
The iterator in the previous function knows the bounds one for all; that's why iterators lead to better optimisation opportunities by the compiler.
Note that len() is evaluated once for all at the beginning of the loop here; this is probably what we want, but if we wanted to reevaluate it at each iteration, then we would have to use a loop {} instruction.
What is discussed here is not specific to the language but to the problem itself.
With a more permissive programming language, the first attempt may have been allowed but would have lead to memory errors; or such language should shift systematically towards the second attempt and pay the cost of bound checking at each iteration.
In the end, your solution with a second loop is probably the best choice.
fn test1() {
let mut v = vec![1, 2, 3, 4, 5, 6, 7, 8];
v.iter_mut().for_each(|e| {
if *e <= 3 {
let n = *e + 100;
// v.push(n) // !!! INCORRECT !!!
// we are trying to reallocate the storage while iterating over it
} else {
*e += 10;
}
});
println!("{:?}", v);
}
fn test2() {
let mut v = vec![1, 2, 3, 4, 5, 6, 7, 8];
for i in 0..v.len() {
let e = &mut v[i];
if *e <= 3 {
let n = *e + 100;
v.push(n);
} else {
*e += 10;
}
}
println!("{:?}", v);
}
fn main() {
test1(); // [1, 2, 3, 14, 15, 16, 17, 18]
test2(); // [1, 2, 3, 14, 15, 16, 17, 18, 101, 102, 103]
}

How to get the minimum value within a vector in Rust?

I'm trying to display the minimum value within a vector in Rust and can't find a good way to do so.
Given a vector of i32 :
let mut v = vec![5, 6, 8, 4, 2, 7];
My goal here is to get the minimum value of that vector without having to sort it.
What is the best way to get the minimum value within a Vec<i32> in Rust ?
let minValue = vec.iter().min();
match minValue {
Some(min) => println!( "Min value: {}", min ),
None => println!( "Vector is empty" ),
}
https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.min
fn min(self) -> Option<Self::Item>
where
Self::Item: Ord,
Returns the minimum element of an iterator.
If several elements are equally minimum, the first element is returned. If the iterator is empty, None is returned.
I found this Gist which has some common C#/.NET Linq operations expressed in Swift and Rust, which is handy: https://gist.github.com/leonardo-m/6e9315a57fe9caa893472c2935e9d589
let mut v = vec![5, 6, 8, 4, 2, 7];
let minValue = *v.iter().min().unwrap();
Hi #octano As Dai has already answered, min/max return Option<> value, so you can only match it as in example:
fn main() {
let vec_to_check = vec![5, 6, 8, 4, 2, 7];
let min_value = vec_to_check.iter().min();
match min_value {
None => println!("Min value was not found"),
Some(i) => println!("Min Value = {}", i)
}
}
Play ground example for Iter.min()

How does one operate over a subset of a vector?

I understand how to operate on an entire vector, though I don't think this is idiomatic Rust:
fn median(v: &Vec<u32>) -> f32 {
let count = v.len();
if count % 2 == 1 {
v[count / 2] as f32
} else {
(v[count / 2] as f32 + v[count / 2 - 1] as f32) / 2.0
}
}
fn main() {
let mut v1 = vec![3, 7, 8, 5, 12, 14, 21, 13, 18];
v1.sort();
println!("{:.*}", 1, median(&v1));
}
But what if I want to operate on only half of this vector? For example, the first quartile is the median of the lower half, and the third quartile is the median of the upper half. My first thought was to construct two new vectors, but that did not seem quite right.
How do I get "half" a vector?
As mentioned, you want to create a slice using the Index trait with a Range:
let slice = &v1[0..v1.len() / 2];
This is yet another reason why it is discouraged to accept a &Vec. The current code would require converting the slice into an allocated Vec. Instead, rewrite it to accept a slice:
fn median(v: &[u32]) -> f32 {
// ...
}
Since you are likely interested in splitting a vector / slice in half and getting both parts, split_at may be relevant:
let (head, tail) = v1.split_at(v1.len() / 2);
println!("{:.*}", 1, median(head));
println!("{:.*}", 1, median(tail));
How to find the median on vector:
fn median(numbers: &mut Vec<i32>) -> i32 {
numbers.sort();
let mid = numbers.len() / 2;
if numbers.len() % 2 == 0 {
mean(&vec![numbers[mid - 1], numbers[mid]]) as i32
} else {
numbers[mid]
}
}
How to get half a vector:
Use Slice:
let slice: &[i32] = &numbers[0..numbers.len() / 2];
Creates a draining iterator
let half: Vec<i32> = numbers.drain(..numbers.len()/2).collect()

How to set a range in a Vec or slice?

My end goal is to shuffle the rows of a matrix (for which I am using nalgebra).
To address this I need to set a mutable range (slice) of an array.
Supposing I have an array as such (let's say it's a 3x3 matrix):
let mut scores = [7, 8, 9, 10, 11, 12, 13, 14, 15];
I have extracted a row like this:
let r = &scores[..].chunks(3).collect::<Vec<_>>()[1];
Now, for the knuth shuffle I need to swap this with another row. What I need to do is:
scores.chunks_mut(3)[0] = r;
however this fails as such:
cannot index a value of type `core::slice::ChunksMut<'_, _>`
Example: http://is.gd/ULkN6j
I ended up doing a loop over and an element by element swap which seems like a cleaner implementation to me:
fn swap_row<T>(matrix: &mut [T], row_src: usize, row_dest: usize, cols: usize){
for c in 0..cols {
matrix.swap(cols * row_src + c, cols * row_dest + c);
}
}
Your code, as you'd like to write it, can never work. You have an array that you are trying to read from and write to at the same time. This will cause you to have duplicated data:
[1, 2, 3, 4]
// Copy last two to first two
[3, 4, 3, 4]
// Copy first two to last two
[3, 4, 3, 4]
Rust will prevent you from having mutable and immutable references to the same thing for this very reason.
cannot index a value of type core::slice::ChunksMut<'_, _>
chunks_mut returns an iterator. The only thing that an iterator is guaranteed to do is return "the next thing". You cannot index it, it is not all available in contiguous memory.
To move things around, you are going to need somewhere temporary to store the data. One way is to copy the array:
let scores = [7, 8, 9, 10, 11, 12, 13, 14, 15];
let mut new_scores = scores;
for (old, new) in scores[0..3].iter().zip(new_scores[6..9].iter_mut()) {
*new = *old;
}
for (old, new) in scores[3..6].iter().zip(new_scores[0..3].iter_mut()) {
*new = *old;
}
for (old, new) in scores[6..9].iter().zip(new_scores[3..6].iter_mut()) {
*new = *old;
}
Then it's a matter of following one of these existing questions to copy from one to the other.
that's probably closer to what You wanted to do:
fn swap_row<T: Clone>(matrix: &mut [T], row_src: usize, row_dest: usize, cols: usize) {
let v = matrix[..].to_vec();
let mut chunks = v.chunks(cols).collect::<Vec<&[T]>>();
chunks.swap(row_src, row_dest);
matrix.clone_from_slice(chunks.into_iter().fold((&[]).to_vec(), |c1, c2| [c1, c2.to_vec()].concat()).as_slice());
}
I would prefer:
fn swap_row<T: Clone>(matrix: &[T], row_src: usize, row_dest: usize, cols: usize) -> Vec<T> {
let mut chunks = matrix[..].chunks(cols).collect::<Vec<&[T]>>();
chunks.swap(row_src, row_dest);
chunks.iter().fold((&[]).to_vec(), |c1, c2| [c1, c2.to_vec()].concat())
}
btw: nalgebra provides unsafe fn as_slice_unchecked(&self) -> &[T] for all kinds of Storage and RawStorage.
Shuffeling this slice avoids the need for row swapping.

Why does Iterator::take_while take ownership of the iterator?

I find it odd that Iterator::take_while takes ownership of the iterator. It seems like a useful feature to be able to take the first x elements which satisfy some function but still leave the rest of the elements available in the original iterator.
I understand that this is incompatible with a lazy implementation of take_while, but still feels useful. Was this just judged not useful enough to include in the standard library, or is there some other problem I'm not seeing?
All the iterator adapters take the original iterator by value for efficiency's sake. Additionally, taking ownership of the original iterator avoids having to deal with lifetimes when it isn't necessary.
If you wish to retain access to the original iterator, you can use by_ref. This introduces one level of indirection, but the programmer chooses to opt into the extra work when the feature is needed:
fn main() {
let v = [1, 2, 3, 4, 5, 6, 7, 8];
let mut i1 = v.iter();
for z in i1.by_ref().take_while(|&&v| v < 4) {
// ^^^^^^^^^
println!("Take While: {}", z);
}
for z in i1 {
println!("Rest: {}", z);
}
}
Has the output
Take While: 1
Take While: 2
Take While: 3
Rest: 5
Rest: 6
Rest: 7
Rest: 8
Iterator::by_ref works because there's an implementation of Iterator for any mutable reference to an iterator:
impl<'_, I> Iterator for &'_ mut I
where
I: Iterator + ?Sized,
This means that you can also take a mutable reference. The parenthesis are needed for precedence:
for z in (&mut i1).take_while(|&&v| v < 4)
Did you note that 4 was missing? That's because once take_while picks a value and decides to not use it, there's nowhere for it to "put it back". Putting it back would require opting into more storage and slowness than is always needed.
I've used the itertools crate to handle cases like this, specifically take_while_ref:
use itertools::Itertools; // 0.9.0
fn main() {
let v = [1, 2, 3, 4, 5, 6, 7, 8];
let mut i1 = v.iter();
for z in i1.take_while_ref(|&&v| v < 4) {
// ^^^^^^^^^^^^^^^
println!("Take While: {}", z);
}
for z in i1 {
println!("Rest: {}", z);
}
}
Take While: 1
Take While: 2
Take While: 3
Rest: 4
Rest: 5
Rest: 6
Rest: 7
Rest: 8
If it's getting too complicated, we may be using the wrong tool.
Note that 4 is present here.
fn main() {
let v = [1, 2, 3, 4, 5, 6, 7, 8];
let mut i1 = v.iter().peekable();
while let Some(z) = i1.next_if(|&n| n < &4) {
println!("Take While: {z}");
}
for z in i1 {
println!("Rest: {z}");
}
}
Take While: 1
Take While: 2
Take While: 3
Rest: 4
Rest: 5
Rest: 6
Rest: 7
Rest: 8
Playground
Yes, the OP asked for take_while and Shepmaster's solution is superb.

Resources