Rust Bytes: ZigZag Merge
Problem Statement:
Implement an iterator that merges two input iterators of i32 by alternating yields (first from iter1, then iter2, etc.) until both are exhausted.
If one ends early, continue with the remaining from the other.
assert_eg!(zigzag_merge(vec![1, 3, 5].into_iter(), vec![2, 4, 6].into_iter()).collect::<Vec<i32>>(), vec![1, 2, 3, 4, 5, 6]);
assert_eq!(zigzag_merge(vec![1, 3].into_iter(), vec![2, 4, 6].into_iter()).collect::<Vec<132>>(), vec![1, 2, 3, 4, 6]);
assert_eq!(zigzag_merge(vec![1, 3, 5].into_iter(), vec![2, 4].into_iter()).collect::<Vec<132>>(), vec![1, 2, 3, 4, 5]);
assert_eq!(zigzag_merge(vec![1, 2, 3].into_iter(), vec![].into_iter()).collect::<Vec<i32>>(), vec![1]);
Note: The last assert is wrong, the right should be vec![1, 2, 3]
Solution:
fn main() {
println!("Zig Zag Merge Iterator");
}
pub struct Zigzag<A, B>
where
A: Iterator<Item = i32>,
B: Iterator<Item = i32>,
{
a: A,
b: B,
turn_a: bool,
}
impl<A, B> Zigzag<A, B>
where
A: Iterator<Item = i32>,
B: Iterator<Item = i32>,
{
pub fn new(a: A, b: B) -> Self {
Zigzag { a, b, turn_a: true }
}
}
pub fn zigzag_merge<A, B>(a: A, b: B) -> Zigzag<A, B>
where
A: Iterator<Item = i32>,
B: Iterator<Item = i32>,
{
Zigzag::new(a, b)
}
impl<A, B> Iterator for Zigzag<A, B>
where
A: Iterator<Item = i32>,
B: Iterator<Item = i32>,
{
type Item = i32;
fn next(&mut self) -> Option<Self::Item> {
if self.turn_a {
match self.a.next() {
Some(v) => {
self.turn_a = false;
Some(v)
}
None => self.b.next(),
}
} else {
match self.b.next() {
Some(v) => {
self.turn_a = true;
Some(v)
}
None => self.a.next(),
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn both_equal_length() {
let out: Vec<i32> = zigzag_merge(vec![1, 3, 5].into_iter(), vec![2, 4, 6].into_iter()).collect();
assert_eq!(out, vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn second_longer() {
let out: Vec<i32> = zigzag_merge(vec![1, 3].into_iter(), vec![2, 4, 6].into_iter()).collect();
assert_eq!(out, vec![1, 2, 3, 4, 6]);
}
#[test]
fn first_longer() {
let out: Vec<i32> = zigzag_merge(vec![1, 3, 5].into_iter(), vec![2, 4].into_iter()).collect();
assert_eq!(out, vec![1, 2, 3, 4, 5]);
}
#[test]
fn second_empty() {
let out: Vec<i32> = zigzag_merge(vec![1, 2, 3].into_iter(), vec![].into_iter()).collect();
assert_eq!(out, vec![1, 2, 3]);
}
#[test]
fn forth_as_per_instructions() {
let out: Vec<i32> = zigzag_merge(vec![1, 2, 3].into_iter(), vec![].into_iter()).collect();
assert_eq!(out, vec![1,]);
}
}
Test Results:
I have included all 4 asserts from the challenge and added a 5th one which is the version of the 4th that passes. Here are the results.
running 5 tests
test tests::both_equal_length ... ok
test tests::second_empty ... ok
test tests::first_longer ... ok
test tests::second_longer ... ok
test tests::forth_as_per_instructions ... FAILED
failures:
---- tests::forth_as_per_instructions stdout ----
thread 'tests::forth_as_per_instructions' (28510400) panicked at src/main.rs:91:9:
assertion `left == right` failed
left: [1, 2, 3]
right: [1]
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::forth_as_per_instructions
Code Repo:
The code can be found in this Github Repo

