Решение на Wordle от Адриян Ибовски

Обратно към всички решения

Към профила на Адриян Ибовски

Резултати

  • 19 точки от тестове
  • 0 бонус точки
  • 19 точки общо
  • 14 успешни тест(а)
  • 1 неуспешни тест(а)

Код

use std::collections::HashMap;
use std::fmt;
use std::fmt::Debug;
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Copy, Clone)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
alphabet: HashMap<String, bool>,
pub guessing_word: String,
word_count: usize,
history: Vec<Word>
}
#[derive(Debug)]
#[derive(Clone)]
pub struct Word {
word: Vec<Letter>
}
#[derive(Debug)]
#[derive(Copy, Clone)]
enum Letter {
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
impl Game {
fn valid_word(alphabet: &HashMap<String, bool>, word: &str) -> Option<char> {
for c in word.chars() {
if !alphabet.contains_key(&c.to_uppercase().to_string()) {
return Some(c);
}
}
None
}
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let mut game_alphabet: HashMap<String, bool> = HashMap::new();
for c in alphabet.chars() {
game_alphabet.insert(c.to_uppercase().to_string(), true);
}
if let Some(error_char) = Game::valid_word(&game_alphabet, word) {
return Err(GameError::NotInAlphabet(error_char));
}
Ok( Game{
status: GameStatus::InProgress,
attempts: 0,
alphabet: game_alphabet,
guessing_word: String::from(word),
word_count: word.chars().count(),
history: Vec::new()} )
}
/// Опитва се да познае търсената дума. Опита е в `guess`.
///
/// Ако играта е приключила, тоест статуса ѝ е `Won` или `Lost`, очакваме да върнете
/// `GameIsOver` със статуса, с който е приключила.
///
/// Ако `guess` има различен брой букви от търсената дума, очакваме да върнете
/// `GameError::WrongLength`. Полето `expected` на грешката трябва да съдържа броя букви на
/// търсената дума, а `actual` да е броя букви на опита `guess`.
///
/// Ако `guess` има правилния брой букви, но има буква, която не е от азбуката на играта,
/// очакваме `GameError::NotInAlphabet` както по-горе, с първия символ от `guess`, който не е
/// от азбуката.
///
/// Метода приема `&mut self`, защото всеки валиден опит (такъв, който не връща грешка) се
/// запазва в играта за по-нататък. Метода връща `Word`, което описва освен самите символи на
/// `guess`, и как тези символи са се напаснали на търсената дума. Също така инкрементира
/// `attempts` с 1.
///
/// След опита за напасване на думата, ако всички букви са уцелени на правилните места,
/// очакваме `state` полето да се промени на `Won`. Иначе, ако `attempts` са станали 5,
/// състоянието трябва да е `Lost`.
///
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
if self.status != GameStatus::InProgress {
return Err(GameError::GameIsOver(self.status.clone()));
}
let guess_count = guess.chars().count();
if guess_count != self.word_count{
return Err(GameError::WrongLength {expected: self.word_count, actual: guess_count});
}
if let Some(error_char) = Game::valid_word(&self.alphabet, guess) {
return Err(GameError::NotInAlphabet(error_char));
}
let mut guess_letters: HashMap<String, usize> = HashMap::new();
for c in self.guessing_word.chars() {
let character = c.to_uppercase().to_string();
if guess_letters.contains_key(&character) {
*guess_letters.get_mut(&character).unwrap() +=1;
} else {
guess_letters.insert(character, 1);
}
}
let mut result_word: Word = Word { word: vec![] };
let mut guessed: usize = 0;
for (index, curr) in guess.chars().enumerate() {
let key = &curr.to_uppercase().to_string();
if self.guessing_word.chars().nth(index).unwrap() == curr {
result_word.word.push(Letter::FullMatch(curr));
guessed += 1;
} else if let Some(cnt) = guess_letters.get_mut(key) {
if *cnt > 0 {
*cnt -=1;
result_word.word.push(Letter::PartialMatch(curr));
}
} else {
result_word.word.push(Letter::NoMatch(curr));
}
}
self.attempts += 1;
if guessed == self.word_count {
self.status = GameStatus::Won;
} else if self.attempts == 5 {
self.status = GameStatus::Lost;
}
self.history.push(result_word.clone());
Ok(result_word)
}
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result_string = String::new();
for letter in &self.word {
match letter {
Letter::FullMatch(val) => result_string.push_str(format!("[{}]", val.to_uppercase().to_string()).as_str()),
Letter::PartialMatch(val) => result_string.push_str(format!("({})", val.to_uppercase().to_string()).as_str()),
Letter::NoMatch(val) => result_string.push_str(format!(">{}<", val.to_uppercase().to_string()).as_str())
}
}
write!(f, "{}", result_string)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut game_result = String::new();
for _cnt in 0..self.word_count {
game_result.push_str("|_|");
}
for history_word in &self.history {
game_result.push_str(format!("\n{}",history_word).as_str())
}
write!(f, "{}",game_result)
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20230111-3772066-173qdfp/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.88s
     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 ... ok
test solution_test::test_game_display_german ... ok
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_german ... ok
test solution_test::test_word_display_bulgarian ... FAILED
test solution_test::test_word_display_with_repetitions ... ok
test solution_test::test_word_not_in_alphabet_on_construction ... ok
test solution_test::test_word_not_in_alphabet_on_guess ... ok
test solution_test::test_word_not_in_alphabet_on_construction_cyrrilic ... ok
test solution_test::test_wrong_length ... ok
test solution_test::test_word_not_in_alphabet_on_guess_cyrillic ... ok

failures:

---- solution_test::test_word_display_bulgarian stdout ----
thread 'solution_test::test_word_display_bulgarian' panicked at 'assertion failed: `(left == right)`
  left: `"(Л)>А<>Е<"`,
 right: `"(Л)>А<(Л)>Е<"`', tests/solution_test.rs:77:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    solution_test::test_word_display_bulgarian

test result: FAILED. 14 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--test solution_test`

История (1 версия и 0 коментара)

Адриян качи първо решение на 23.11.2022 12:39 (преди почти 3 години)