Hey everyone
I have written this code:
use std::collections::HashMap;
pub struct PairMatcher<T, I>
where
T: PartialEq,
I: IntoIterator<Item = T>,
{
pairs: HashMap<T, T>,
search_input: I,
}
impl<T, I> PairMatcher<T, I>
where
T: PartialEq,
I: IntoIterator<Item = T>,
{
pub fn new(pairs: HashMap<T, T>, search_input: I) -> Self {
Self {
pairs,
search_input,
}
}
pub fn count_pairs(self) -> Option<usize> {
let mut stack = vec![];
let mut counter = 0;
let left_elements = Vec::from_iter(self.pairs.keys());
let right_elements = Vec::from_iter(self.pairs.values());
for element in self.search_input {
if left_elements.contains(&&element) {
stack.push(element)
} else if right_elements.contains(&&element) {
match stack.pop() {
Some(_) => counter += 1,
None => return None,
}
}
}
if !stack.is_empty() {
return None;
}
Some(counter)
}
pub fn has_matching_pairs(self) -> bool {
match self.count_pairs() {
Some(_) => true,
None => false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simple_str_match() {
let pairs = HashMap::from([('{', '}')]);
let pair_matcher = PairMatcher::new(pairs, "{}{}".chars());
assert_eq!(pair_matcher.count_pairs(), Some(2));
}
#[test]
fn test_simple_int_match() {
let pairs = HashMap::from([(1, 2)]);
let pair_matcher = PairMatcher::new(pairs, vec![1, 2, 3, 4, 5, 1, 2, 56, 1, 2].into_iter());
assert_eq!(pair_matcher.count_pairs(), Some(3));
}
#[test]
fn test_failed_match() {
let pairs = HashMap::from([(1, 2)]);
let pair_matcher = PairMatcher::new(pairs, vec![1, 2, 3, 4, 5, 1, 2, 56, 1].into_iter());
assert!(!pair_matcher.has_matching_pairs())
}
#[test]
fn test_complex_match() {
let pairs = HashMap::from([('{', '}')]);
let pair_matcher = PairMatcher::new(pairs, "{{{{{{{{}{}{}{}{}{{}}}}}}}}{}{}{}}".chars());
assert!(pair_matcher.has_matching_pairs())
}
}
and it works. but the code looks quite ugly in my opinion.
Also I would like to have count_pairs to have &self and not self, so it does not move search_input.
I don't seem to find a way for it.
Any help would be appreciated. I really want to get better at rust.