Решение на Wordle от Мартин Маринов

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

Към профила на Мартин Маринов

Резултати

  • 15 точки от тестове
  • 0 бонус точки
  • 15 точки общо
  • 11 успешни тест(а)
  • 4 неуспешни тест(а)

Код

#[derive(Debug)]
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,
pub alphabet: Vec<char>,
pub word: String,
pub history: Vec<Word>,
}
#[derive(Debug)]
pub struct Word {
pub symbols: Vec<char>,
pub symbols_match: Vec<i8>,
}
impl Game {
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let alphabet: Vec<char> = alphabet.chars().collect();
for symbol in word.chars() {
if !alphabet.contains(&symbol) {
return Err(GameError::NotInAlphabet(symbol));
}
}
Ok(Game {
status: GameStatus::InProgress,
attempts: 0,
alphabet,
word: String::from(word),
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> {
match self.status {
GameStatus::Won => Err(GameError::GameIsOver(GameStatus::Won)),
GameStatus::Lost => Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::InProgress => {
if guess.len() != self.word.len() {
return Err(GameError::WrongLength {
expected: self.word.len(),
actual: guess.len(),
});
}
for symbol in guess.chars() {
if !self.alphabet.contains(&symbol) {
return Err(GameError::NotInAlphabet(symbol));
}
}
let mut is_matching = true;
let symbols: Vec<char> = guess.chars().collect();
let mut symbols_match: Vec<i8> = Vec::new();
let guess: Vec<char> = guess.chars().collect();
let word: Vec<char> = self.word.chars().collect();
for pos in 0..guess.len() {
if guess[pos] == word[pos] {
symbols_match.push(0);
} else if word.contains(&guess[pos]) {
symbols_match.push(1);
is_matching = false;
} else {
symbols_match.push(-1);
is_matching = false;
}
}
self.history.push(Word {
symbols: symbols.clone(),
symbols_match: symbols_match.clone(),
});
self.attempts += 1;
if is_matching {
self.status = GameStatus::Won;
} else if self.attempts == 5 {
self.status = GameStatus::Lost;
}
Ok(Word {
symbols,
symbols_match,
})
}
}
}
}
use std::fmt;
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for pos in 0..self.symbols_match.len() {
let value = self.symbols[pos].to_uppercase();
let match_value = self.symbols_match[pos];
match match_value {
0 => f.write_fmt(format_args!("[{}]", value)).ok(),
1 => f.write_fmt(format_args!("({})", value)).ok(),
_ => f.write_fmt(format_args!(">{}<", value)).ok(),
};
}
Ok(())
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for _ in 0..self.word.len() {
f.write_str("|_|").ok();
}
for word in &self.history {
f.write_fmt(format_args!("\n{}", word)).ok();
}
Ok(())
}
}

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

Compiling solution v0.1.0 (/tmp/d20230111-3772066-1io0i9g/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.85s
     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_display_with_repetitions ... ok
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_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`

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

Мартин качи първо решение на 24.11.2022 14:27 (преди почти 3 години)