wordl/src/model/charstatus.rs
itsscb a8114230b8 chore: removes old pages
feat: adds word struct
2024-09-09 14:39:19 +02:00

141 lines
4.2 KiB
Rust

use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Word(Vec<CharStatus<String>>);
impl Word {
pub fn chars(&self) -> Vec<CharStatus<String>> {
self.0.clone()
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum CharStatus<T> {
NotContained(T),
Contained(T),
Match(T),
Unknown,
}
pub(super) fn compare_strings(s1: &str, s2: &str) -> Word {
let mut result: Vec<CharStatus<String>> = Vec::with_capacity(s1.len());
result.resize_with(s1.len(), || CharStatus::Unknown);
let mut s1_char_count: HashMap<char, usize> = HashMap::new();
let mut s2_char_count: HashMap<char, usize> = HashMap::new();
for c in s1.chars() {
*s1_char_count.entry(c).or_insert(0) += 1;
}
for ((c1, c2), res) in s1.chars().zip(s2.chars()).zip(result.iter_mut()) {
if c1 == c2 {
*res = CharStatus::Match(c2.to_string());
*s2_char_count.entry(c2).or_insert(0) += 1;
} else {
*res = CharStatus::Unknown;
}
}
for (res, c2) in result.iter_mut().zip(s2.chars()) {
if res == &CharStatus::Unknown {
let c1_count = s1_char_count.get(&c2).unwrap_or(&0);
let c2_count = s2_char_count.get(&c2).unwrap_or(&0);
if *c1_count > 0 && c1_count > c2_count {
*res = CharStatus::Contained(c2.to_string());
*s2_char_count.entry(c2).or_insert(0) += 1;
} else {
*res = CharStatus::NotContained(c2.to_string());
}
}
}
Word(result)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_compare_strings() {
let source = "HALLO";
let want = Word(vec![
CharStatus::NotContained("0".to_owned()),
CharStatus::NotContained("0".to_owned()),
CharStatus::NotContained("0".to_owned()),
CharStatus::NotContained("0".to_owned()),
CharStatus::NotContained("0".to_owned()),
]);
let input = "00000";
let got = compare_strings(source, input);
assert_eq!(want, got);
let source = "HALLO";
let want = Word(vec![
CharStatus::NotContained("L".to_owned()),
CharStatus::NotContained("L".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::NotContained("L".to_owned()),
]);
let input = "LLLLL";
let got = compare_strings(source, input);
assert_eq!(want, got);
let want = Word(vec![
CharStatus::Match("H".to_owned()),
CharStatus::Match("A".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::Match("O".to_owned()),
]);
let input = "HALLO";
let got = compare_strings(source, input);
assert_eq!(want, got);
let want = Word(vec![
CharStatus::Match("H".to_owned()),
CharStatus::NotContained("L".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::Match("O".to_owned()),
]);
let input = "HLLLO";
let got = compare_strings(source, input);
assert_eq!(want, got);
let want = Word(vec![
CharStatus::Match("H".to_owned()),
CharStatus::Contained("L".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::NotContained("I".to_owned()),
CharStatus::NotContained("L".to_owned()),
]);
let input = "HLLIL";
let got = compare_strings(source, input);
assert_eq!(want, got);
let want = Word(vec![
CharStatus::Contained("L".to_owned()),
CharStatus::NotContained("L".to_owned()),
CharStatus::Match("L".to_owned()),
CharStatus::Contained("A".to_owned()),
CharStatus::Match("O".to_owned()),
]);
let input = "LLLAO";
let got = compare_strings(source, input);
assert_eq!(want, got);
}
}