Решение на Wordle от Чудомир Ченков
Резултати
- 15 точки от тестове
- 0 бонус точки
- 15 точки общо
- 11 успешни тест(а)
- 4 неуспешни тест(а)
Код
use std::fmt;
use std::fmt::Write;
#[derive(Debug, Clone, Copy)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug, Clone)]
pub enum Letter {
Unknown(char),
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[derive(Debug, Clone)]
pub struct Word {
pub letters: Vec<Letter>,
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub alphabet: String,
pub word: String,
pub guesses: Vec<Word>,
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut res = String::new();
for letter in &self.letters {
match letter {
Letter::FullMatch(ch) => write!(res, "[{}]", ch.to_uppercase().to_string()),
Letter::PartialMatch(ch) => write!(res, "({})", ch.to_uppercase().to_string()),
Letter::NoMatch(ch) => write!(res, ">{}<", ch.to_uppercase().to_string()),
Letter::Unknown(_) => panic!("Unknown letter")
}.unwrap();
}
write!(f, "{}", res)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let placeholder = "|_|".repeat(self.word.len()) + if self.guesses.len() > 0 { "\n" } else { "" };
let res = self.guesses.iter().map(|guess| guess.to_string()).collect::<Vec<_>>().join("\n");
write!(f, "{}{}", placeholder, res)
}
}
impl Word {
pub fn new() -> Self {
Word { letters: Vec::new(), }
}
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
for letter in word.chars() {
if !alphabet.contains(letter) {
return Err(GameError::NotInAlphabet(letter));
}
}
Ok(Game {
status: GameStatus::InProgress,
attempts: 0,
alphabet: alphabet.to_string(),
word: word.to_string(),
guesses: Vec::new(),
})
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
if !matches!(self.status, GameStatus::InProgress) {
return Err(GameError::GameIsOver(self.status));
}
if guess.len() != self.word.len() {
return Err(GameError::WrongLength { expected: self.word.len(), actual: guess.len() });
}
for letter in guess.chars() {
if !self.alphabet.contains(letter) {
return Err(GameError::NotInAlphabet(letter));
}
}
let mut guess_eval = Word::new();
for (idx, letter) in guess.chars().enumerate() {
if !self.word.contains(letter) {
guess_eval.letters.push(Letter::NoMatch(letter));
} else {
if self.word.chars().nth(idx).unwrap() == letter {
guess_eval.letters.push(Letter::FullMatch(letter));
} else {
guess_eval.letters.push(Letter::PartialMatch(letter));
}
}
}
self.attempts += 1;
if self.attempts >= 5 {
self.status = GameStatus::Lost;
} else {
// assume the game is finished
// if a letter is not fully matched go back to InProgress state
self.status = GameStatus::Won;
for letter in &guess_eval.letters {
if !matches!(letter, Letter::FullMatch(_)) {
self.status = GameStatus::InProgress;
}
}
}
self.guesses.push(guess_eval.clone());
Ok(guess_eval)
}
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20230111-3772066-xslih8/solution) Finished test [unoptimized + debuginfo] target(s) in 0.92s Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01) running 15 tests test solution_test::test_game_display ... ok test solution_test::test_game_display_cyrillic ... FAILED test solution_test::test_game_display_german ... FAILED test solution_test::test_game_state_1 ... ok test solution_test::test_game_state_2 ... ok test solution_test::test_game_state_3 ... ok test solution_test::test_word_display ... ok test solution_test::test_word_display_bulgarian ... ok test solution_test::test_word_display_german ... FAILED test solution_test::test_word_not_in_alphabet_on_construction ... ok test solution_test::test_word_not_in_alphabet_on_construction_cyrrilic ... ok test solution_test::test_word_display_with_repetitions ... ok test solution_test::test_word_not_in_alphabet_on_guess ... ok test solution_test::test_word_not_in_alphabet_on_guess_cyrillic ... FAILED test solution_test::test_wrong_length ... ok failures: ---- solution_test::test_game_display_cyrillic stdout ---- thread 'solution_test::test_game_display_cyrillic' panicked at 'assertion failed: `(left == right)` left: `"|_||_||_||_||_||_|"`, right: `"|_||_||_|"`', tests/solution_test.rs:119:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ---- solution_test::test_game_display_german stdout ---- thread 'solution_test::test_game_display_german' panicked at 'assertion failed: `(left == right)` left: `"|_||_||_||_||_|"`, right: `"|_||_||_|"`', tests/solution_test.rs:133:5 ---- solution_test::test_word_display_german stdout ---- thread 'solution_test::test_word_display_german' panicked at 'assertion failed: `(left == right)` left: `"|_||_||_||_||_|"`, right: `"|_||_||_|"`', tests/solution_test.rs:87:5 ---- solution_test::test_word_not_in_alphabet_on_guess_cyrillic stdout ---- thread 'solution_test::test_word_not_in_alphabet_on_guess_cyrillic' panicked at 'Expression Err(WrongLength { expected: 4, actual: 8 }) does not match the pattern "Err(GameError::NotInAlphabet('х'))"', tests/solution_test.rs:46:5 failures: solution_test::test_game_display_cyrillic solution_test::test_game_display_german solution_test::test_word_display_german solution_test::test_word_not_in_alphabet_on_guess_cyrillic test result: FAILED. 11 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--test solution_test`