Решение на Wordle от Георги Бойчев

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

Към профила на Георги Бойчев

Резултати

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

Код

#[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 game_alphabet: String,
answer: String,
pub previous_guesses: Vec<String>
// Каквито други полета ви трябват
}
#[derive(Debug)]
pub struct Word {
pub checked_symbols: String
}
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));
}
}
let mut starting_state = String::new();
for (_, _) in word.chars().enumerate() {
starting_state.push_str("|_|");
}
let mut prev_guesses_vec : Vec<String> = Vec::new();
prev_guesses_vec.push(starting_state);
let game = Game {
status: GameStatus::InProgress,
attempts: 0,
game_alphabet: String::from(alphabet),
answer: String::from(word),
previous_guesses: prev_guesses_vec
};
Ok(game)
}
/// Опитва се да познае търсената дума. Опита е в `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::Lost => return Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::Won => return Err(GameError::GameIsOver(GameStatus::Won)),
_ => {}
}
if guess.len() != self.answer.len() {
return Err(GameError::WrongLength { expected: (self.answer.len()), actual: (guess.len()) });
}
for c in guess.chars() {
if !(self.game_alphabet.contains(c)) {
return Err(GameError::NotInAlphabet(c));
}
}
let word_checked_symbols = String::new();
let mut result = Word {
checked_symbols: word_checked_symbols
};
let answer_vec: Vec<char> = self.answer.chars().collect();
for (i, c) in guess.chars().enumerate() {
if c.eq(&answer_vec[i]) {
result.checked_symbols.push('[');
result.checked_symbols.push_str(&c.to_uppercase().to_string());
result.checked_symbols.push(']');
}
else if answer_vec.contains(&c) {
result.checked_symbols.push('(');
result.checked_symbols.push_str(&c.to_uppercase().to_string());
result.checked_symbols.push(')');
}
else {
result.checked_symbols.push('>');
result.checked_symbols.push_str(&c.to_uppercase().to_string());
result.checked_symbols.push('<');
}
}
self.attempts += 1;
self.previous_guesses.push(String::from(result.checked_symbols.clone()));
if guess.eq_ignore_ascii_case(&self.answer) {
self.status = GameStatus::Won;
} else if self.attempts == 5{
self.status = GameStatus::Lost;
}
Ok(result)
}
}
use std::fmt;
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.checked_symbols)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut res = String::new();
for (i, s) in self.previous_guesses.iter().enumerate() {
res.push_str(&s);
if i != self.previous_guesses.len() - 1 {
res.push('\n');
}
}
write!(f, "{}", res)
}
}

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

Compiling solution v0.1.0 (/tmp/d20230111-3772066-631seg/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.79s
     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_state_1 ... ok
test solution_test::test_game_display_german ... ok
test solution_test::test_game_state_2 ... ok
test solution_test::test_word_display ... ok
test solution_test::test_game_state_3 ... ok
test solution_test::test_word_display_bulgarian ... ok
test solution_test::test_word_display_german ... 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_display_with_repetitions ... ok
test solution_test::test_word_not_in_alphabet_on_guess_cyrillic ... FAILED
test solution_test::test_wrong_length ... ok

failures:

---- 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
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    solution_test::test_word_not_in_alphabet_on_guess_cyrillic

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`

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

Георги качи първо решение на 24.11.2022 11:41 (преди почти 3 години)

Георги качи решение на 24.11.2022 11:54 (преди почти 3 години)

#[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 game_alphabet: String,
answer: String,
pub previous_guesses: Vec<String>
// Каквито други полета ви трябват
}
#[derive(Debug)]
pub struct Word {
pub checked_symbols: String
}
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));
}
}
let mut starting_state = String::new();
for (_, _) in word.chars().enumerate() {
starting_state.push_str("|_|");
}
let mut prev_guesses_vec : Vec<String> = Vec::new();
prev_guesses_vec.push(starting_state);
let game = Game {
status: GameStatus::InProgress,
attempts: 0,
game_alphabet: String::from(alphabet),
answer: String::from(word),
previous_guesses: prev_guesses_vec
};
Ok(game)
}
/// Опитва се да познае търсената дума. Опита е в `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::Lost => return Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::Won => return Err(GameError::GameIsOver(GameStatus::Won)),
_ => {}
}
if guess.len() != self.answer.len() {
return Err(GameError::WrongLength { expected: (self.answer.len()), actual: (guess.len()) });
}
for c in guess.chars() {
if !(self.game_alphabet.contains(c)) {
return Err(GameError::NotInAlphabet(c));
}
}
let word_checked_symbols = String::new();
let mut result = Word {
checked_symbols: word_checked_symbols
};
let answer_vec: Vec<char> = self.answer.chars().collect();
for (i, c) in guess.chars().enumerate() {
if c.eq(&answer_vec[i]) {
result.checked_symbols.push('[');
result.checked_symbols.push_str(&c.to_uppercase().to_string());
result.checked_symbols.push(']');
}
else if answer_vec.contains(&c) {
result.checked_symbols.push('(');
result.checked_symbols.push_str(&c.to_uppercase().to_string());
result.checked_symbols.push(')');
}
else {
result.checked_symbols.push('>');
result.checked_symbols.push_str(&c.to_uppercase().to_string());
result.checked_symbols.push('<');
}
}
self.attempts += 1;
self.previous_guesses.push(String::from(result.checked_symbols.clone()));
if guess.eq_ignore_ascii_case(&self.answer) {
self.status = GameStatus::Won;
} else if self.attempts == 5{
self.status = GameStatus::Lost;
}
Ok(result)
}
}
-use std::{fmt, ops::Add};
+use std::fmt;
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.checked_symbols)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut res = String::new();
for (i, s) in self.previous_guesses.iter().enumerate() {
res.push_str(&s);
if i != self.previous_guesses.len() - 1 {
res.push('\n');
}
}
write!(f, "{}", res)
}
}