Решение на Wordle от Атанас Добрев

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

Към профила на Атанас Добрев

Резултати

  • 13 точки от тестове
  • 0 бонус точки
  • 13 точки общо
  • 10 успешни тест(а)
  • 5 неуспешни тест(а)

Код

use std::collections::HashSet;
#[derive(Debug, 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,
pub alphabet: Vec<char>,
pub word: Vec<char>,
pub guesses: Vec<Word>,
// Каквито други полета ви трябват
}
#[derive(Debug)]
pub struct Word {
pub letters: Vec<char>,
pub letter_status: Vec<u8>,
}
impl Game {
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
for c in word.chars() {
if !alphabet.contains(c) {
return Err(GameError::NotInAlphabet(c))
}
}
Ok(
Game{
status: GameStatus::InProgress,
attempts: 0,
alphabet: alphabet.chars().collect::<Vec<_>>(),
word: word.chars().collect::<Vec<_>>(),
guesses: 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 matches!(self.status, GameStatus::Won) || matches!(self.status, GameStatus::Lost) {
return Err(GameError::GameIsOver(self.status))
}
if self.word.len() != guess.len() {
return Err(GameError::WrongLength {
expected: self.word.len(),
actual: guess.len(),
})
}
for c in guess.chars() {
if !self.alphabet.contains(&c) {
return Err(GameError::NotInAlphabet(c))
}
}
let mut letters: Vec<char> = Vec::new();
let mut letter_status: Vec<u8> = Vec::new();
let mut not_in_place: HashSet<char> = HashSet::new();
for (i, c) in guess.chars().enumerate() {
letters.push(c);
if c == self.word[i] {
letter_status.push(2);
} else {
letter_status.push(0);
not_in_place.insert(self.word[i]);
}
}
for (i, c) in guess.chars().enumerate() {
if letter_status[i] == 0 && not_in_place.contains(&c) {
letter_status[i] = 1;
}
}
self.attempts += 1;
if not_in_place.is_empty() {
self.status = GameStatus::Won;
} else if self.attempts == 5 {
self.status = GameStatus::Lost;
}
let word: Word = Word {
letters: letters.clone(),
letter_status: letter_status.clone(),
};
let word_to_return: Word = Word {letters, letter_status};
self.guesses.push(word);
Ok(word_to_return)
}
}
use std::fmt;
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, c) in self.letters.iter().enumerate() {
if self.letter_status[i] == 0 { // Not in place nor anywhere in the word.
write!(f, ">{}<", c.to_uppercase().to_string());
}
else if self.letter_status[i] == 1 { // Not in place but in the word.
write!(f, "({})", c.to_uppercase().to_string());
}
else if self.letter_status[i] == 2 { // In place correct letter.
write!(f, "[{}]", c.to_uppercase().to_string());
}
}
Ok(())
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for _ in &self.word {
write!(f, "|_|");
}
for word in self.guesses.iter() {
write!(f, "\n{}", word);
}
Ok(())
}
}
fn main() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut game = Game::new(english_letters, "rebus").unwrap();
game.guess_word("route").unwrap();
game.guess_word("kauec").unwrap();
game.guess_word("kauce").unwrap();
game.guess_word("rebus").unwrap();
println!("{}", game);
println!("{}", game.guess_word("neshto").is_err());
}
#[test]
fn test_basic() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
// Конструираме по два различни начина, just in case -- няма причина да не работи и с двата.
assert!(Game::new(english_letters, "!!!").is_err());
let mut game = Game::new(&String::from(english_letters), "abc").unwrap();
assert!(matches!(game.status, GameStatus::InProgress));
assert_eq!(game.attempts, 0);
assert_eq!(game.to_string(), "|_||_||_|");
assert_eq!(game.guess_word("abc").unwrap().to_string(), "[A][B][C]");
assert_eq!(game.to_string(), "|_||_||_|\n[A][B][C]");
assert_eq!(game.guess_word("gos").is_err(), true);
// let english_letters = "abcdefghijklmnopqrstuvwxyz";
// let mut game = Game::new(english_letters, "rebus").unwrap();
//
// game.guess_word("route").unwrap();
// game.guess_word("rebus").unwrap();
//
// assert_eq!(game.to_string(), "|_||_||_||_||_|\n[R]>O<(U)>T<(E)\n[R][E][B][U][S]");
}

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

Compiling solution v0.1.0 (/tmp/d20230111-3772066-5nwed4/solution)
warning: function `main` is never used
   --> src/lib.rs:174:4
    |
174 | fn main() {
    |    ^^^^
    |
    = note: `#[warn(dead_code)]` on by default

warning: unused `Result` that must be used
   --> src/lib.rs:148:17
    |
148 |                 write!(f, ">{}<", c.to_uppercase().to_string());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this `Result` may be an `Err` variant, which should be handled
    = note: `#[warn(unused_must_use)]` on by default
    = note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused `Result` that must be used
   --> src/lib.rs:151:17
    |
151 |                 write!(f, "({})", c.to_uppercase().to_string());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this `Result` may be an `Err` variant, which should be handled
    = note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused `Result` that must be used
   --> src/lib.rs:154:17
    |
154 |                 write!(f, "[{}]", c.to_uppercase().to_string());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this `Result` may be an `Err` variant, which should be handled
    = note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused `Result` that must be used
   --> src/lib.rs:164:13
    |
164 |             write!(f, "|_|");
    |             ^^^^^^^^^^^^^^^^
    |
    = note: this `Result` may be an `Err` variant, which should be handled
    = note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: unused `Result` that must be used
   --> src/lib.rs:168:13
    |
168 |             write!(f, "\n{}", word);
    |             ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: this `Result` may be an `Err` variant, which should be handled
    = note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: `solution` (lib) generated 6 warnings
    Finished test [unoptimized + debuginfo] target(s) in 0.90s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 15 tests
test solution_test::test_game_display_cyrillic ... FAILED
test solution_test::test_game_display ... ok
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 ... FAILED
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_wrong_length ... ok
test solution_test::test_word_not_in_alphabet_on_guess_cyrillic ... FAILED

failures:

---- solution_test::test_game_display_cyrillic stdout ----
thread 'solution_test::test_game_display_cyrillic' panicked at 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 3, actual: 6 }', tests/solution_test.rs:120:28
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 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 3, actual: 5 }', tests/solution_test.rs:134:28

---- solution_test::test_word_display_bulgarian stdout ----
thread 'solution_test::test_word_display_bulgarian' panicked at 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 4, actual: 8 }', tests/solution_test.rs:77:40

---- solution_test::test_word_display_german stdout ----
thread 'solution_test::test_word_display_german' panicked at 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 3, actual: 5 }', tests/solution_test.rs:88:39

---- 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_bulgarian
    solution_test::test_word_display_german
    solution_test::test_word_not_in_alphabet_on_guess_cyrillic

test result: FAILED. 10 passed; 5 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 03:51 (преди почти 3 години)