I've been trying to lean more into Rust's functional language features so I'm trying to take this function:
-
fn minimum_length(s: String) -> i32 { if s.len() <= 1 { return s.len() as i32; } let mut len_after_deleting_similar_ends = s.len(); let x = len_after_deleting_similar_ends / 2; for (first_char, last_char) in zip(s.chars().take(x), s.chars().rev().take(x)) { if first_char == last_char { len_after_deleting_similar_ends -= 2 } else { return len_after_deleting_similar_ends as i32 } }; len_after_deleting_similar_ends as i32 }
and rewrite it to use the fold method instead of a loop, currently my code is:
-
fn minimum_length_fold(s: String) -> i32 { if s.len() <= 1 { return s.len() as i32; } let len_after_deleting_similar_ends = zip(s.chars().take(s.len() / 2), s.chars().rev().take(s.len() / 2)) .fold(s.len(), |acc, (first_char, last_char)| { println!("{first_char} {last_char} {acc}"); if first_char == last_char { acc - 2 } else { return acc; } }); len_after_deleting_similar_ends as i32 }
However, any case that would cause an early return in the first function (except for an early return on the final pair of letters) will give an incorrect result. This is because the return returns to the fold rather than returning to the caller of minimum_length_fold and therefore the functionality is the same as if return was omitted.
How can I change this so that a mismatching pair of letters results in an early return or some similarly efficient solution?
My tests are:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
assert_eq!(minimum_length(String::from("ca")), 2)
}
#[test]
fn test_2() {
assert_eq!(minimum_length(String::from("cabaabac")), 0);
}
#[test]
fn test_3() {
assert_eq!(minimum_length(String::from("caaaabac")), 4);
}
}
minimum_length will pass all three whereas minimum_length_fold will fail test_3 on account of it not returning early and the accumulator has currently been reduced due to the matching 'a' at index 3 and index 4, it passes test_2 despite the lack of an early return as there are no subsequent matching pairs of letters which would cause the accumulator to be reduced and therefore the answer is correct despite the flawed logic.
I am guessing what is actually asked for is how to do this using iterators. Here is a way without using fold (using count instead):
This is probably as fast as the first solution.
One thing to consider is how to handle for example "a". As you have written the function, it should return 1, but both sides of the string are the same, so maybe the 'a' should be removed, and the function return 0.