use super::model::{KeyboardHints, LetterState, LetterStatus};
pub fn check(wordle: String, guess: String) -> Vec<LetterStatus> {
let mut output: Vec<LetterStatus> = Vec::with_capacity(5);
if wordle.len() != 5 && guess.len() != 5 {
panic!("5 letter wordle and guess word is needed. Aborting");
}
let wordle_letters: Vec<char> = wordle.chars().collect();
let guess_letters: Vec<char> = guess.chars().collect();
for position in 0..5 {
let wordle_letter = wordle_letters[position];
let guess_letter = guess_letters[position];
if wordle_letter == guess_letter {
output.push(LetterStatus {
letter: guess_letter,
status: LetterState::Correct,
})
} else {
if !wordle_letters.contains(&guess_letter) {
output.push(LetterStatus {
letter: guess_letter,
status: LetterState::NotPresent,
})
} else {
let wordle_occurences =
wordle_letters.clone().into_iter().fold(0, |acc, letter| {
if letter == guess_letter {
acc + 1
} else {
acc
}
});
let guess_occurences = guess_letters.clone().into_iter().fold(0, |acc, letter| {
if letter == guess_letter {
acc + 1
} else {
acc
}
});
if wordle_occurences >= guess_occurences {
output.push(LetterStatus {
letter: guess_letter,
status: LetterState::Incorrect,
})
} else {
output.push(LetterStatus {
letter: guess_letter,
status: LetterState::NotPresent,
})
}
}
}
}
output
}
pub fn is_correct_guess(input: Vec<LetterStatus>) -> bool {
input.iter().all(|x| x.status == LetterState::Correct)
}
pub fn update_keyboard_hints<'a>(
hints: &'a mut KeyboardHints,
statuses: Vec<LetterStatus>,
) -> &'a mut KeyboardHints {
for status in statuses {
if !hints.contains_key(&status.letter) {
hints.insert(status.letter.clone(), status.status.clone());
} else {
match status.status {
LetterState::Incorrect => {
if let Some(current_status) = hints.get(&status.letter) {
if *current_status != LetterState::Correct {
hints.insert(status.letter.clone(), status.status.clone());
}
}
}
LetterState::Unknown | LetterState::NotPresent => {
if let Some(current_status) = hints.get(&status.letter) {
if *current_status != LetterState::Correct
&& *current_status != LetterState::Incorrect
{
hints.insert(status.letter.clone(), status.status.clone());
}
}
}
LetterState::Correct => {
hints.insert(status.letter.clone(), LetterState::Correct);
}
}
}
}
hints
}
#[cfg(test)]
mod tests {
use crate::wordle::model::{LetterState, LetterStatus};
use crate::wordle::utils::*;
use std::collections::HashMap;
#[test]
fn test_check() {
let output = check("helio".into(), "hello".into());
let expected: Vec<LetterStatus> = vec![
LetterStatus {
letter: 'h',
status: LetterState::Correct,
},
LetterStatus {
letter: 'e',
status: LetterState::Correct,
},
LetterStatus {
letter: 'l',
status: LetterState::Correct,
},
LetterStatus {
letter: 'l',
status: LetterState::NotPresent,
},
LetterStatus {
letter: 'o',
status: LetterState::Correct,
},
];
assert_eq!(output, expected);
}
#[test]
fn test_letter_status() {
let all_correct_input: Vec<LetterStatus> = vec![
LetterStatus {
letter: 'p',
status: LetterState::Correct,
},
LetterStatus {
letter: 'i',
status: LetterState::Correct,
},
LetterStatus {
letter: 'o',
status: LetterState::Correct,
},
LetterStatus {
letter: 'u',
status: LetterState::Correct,
},
LetterStatus {
letter: 's',
status: LetterState::Correct,
},
];
assert!(is_correct_guess(all_correct_input));
let not_correct_input: Vec<LetterStatus> = vec![
LetterStatus {
letter: 'x',
status: LetterState::Unknown,
},
LetterStatus {
letter: 'i',
status: LetterState::Correct,
},
LetterStatus {
letter: 'o',
status: LetterState::Correct,
},
LetterStatus {
letter: 'u',
status: LetterState::Correct,
},
LetterStatus {
letter: 's',
status: LetterState::Correct,
},
];
assert_eq!(is_correct_guess(not_correct_input), false);
}
#[test]
fn test_keyboard_hints() {
let wordle = String::from("pious");
let mut hints: KeyboardHints = HashMap::new();
let statuses: Vec<LetterStatus> = check(wordle.clone(), "piano".into());
update_keyboard_hints(&mut hints, statuses);
assert_eq!(*hints.get(&'p').unwrap(), LetterState::Correct);
assert_eq!(*hints.get(&'i').unwrap(), LetterState::Correct);
assert_eq!(*hints.get(&'a').unwrap(), LetterState::NotPresent);
assert_eq!(*hints.get(&'n').unwrap(), LetterState::NotPresent);
assert_eq!(*hints.get(&'o').unwrap(), LetterState::Incorrect);
assert_eq!(hints.get(&'x'), None);
let statuses: Vec<LetterStatus> = check(wordle.clone(), "smile".into());
update_keyboard_hints(&mut hints, statuses);
assert_eq!(*hints.get(&'i').unwrap(), LetterState::Correct);
let wordle = "below";
hints.clear();
let statuses: Vec<LetterStatus> = check(wordle.into(), "hello".into());
update_keyboard_hints(&mut hints, statuses);
assert_eq!(*hints.get(&'l').unwrap(), LetterState::Correct);
}
}