Search code examples
stringalgorithmrustmergerust-cargo

Algorithm for Alternate merge strings in rust


Here is my code for alternate merge string in rust. I am not getting the expected output. It works fine for equal length strings. Issue is when we have unequal strings it skips one character.

impl Solution {
    pub fn merge_alternately(word1: String, word2: String) -> String {
        let mut merged = String::new();
        let mut chars1 = word1.chars();
        let mut chars2 = word2.chars();

        while let (Some(c1), Some(c2)) = (chars1.next(), chars2.next()) {
            merged.push(c1);
            merged.push(c2);
        }
        // Append any remaining characters from word1
        while let Some(c1) = chars1.next() {
            merged.push(c1);
        }

        // Append any remaining characters from word2
        while let Some(c2) = chars2.next() {
            merged.push(c2);
        }
        merged
    }
}

Here is test case failure:

Input word1 = "ab" word2 = "pqrs"

Current Output "apbqs"

Expected Output "apbqrs"


Solution

  • Your while let (Some(c1), Some(c2)) doesn't doesn't match if only one of the two returns a character. This causes said character to be skipped.

    Your three while let loops can me merged to a single loop{match}, requiring all cases to be handled properly:

    pub fn merge_alternately(word1: String, word2: String) -> String {
        let mut merged = String::new();
        let mut chars1 = word1.chars();
        let mut chars2 = word2.chars();
    
        loop {
            match (chars1.next(), chars2.next()) {
                (Some(c1), Some(c2)) => merged.extend([c1, c2]),
                (Some(c1), None) => merged.push(c1),
                (None, Some(c2)) => merged.push(c2),
                (None, None) => break,
            }
        }
    
        merged
    }
    
    fn main() {
        println!("{}", merge_alternately("ab".into(), "pqrs".into()));
    }
    
    apbqrs
    

    Further, if you are allowed to use libraries, the pretty much standard library for iterators is itertools. It has an .interleave() function which does exactly what you need:

    use itertools::Itertools;
    
    pub fn merge_alternately(word1: String, word2: String) -> String {
        word1.chars().interleave(word2.chars()).collect()
    }
    
    fn main() {
        println!("{}", merge_alternately("ab".into(), "pqrs".into()));
    }
    
    apbqrs