Решение на Wordle от Станислав Христов
Към профила на Станислав Христов
Резултати
- 13 точки от тестове
- 0 бонус точки
- 13 точки общо
- 10 успешни тест(а)
- 5 неуспешни тест(а)
Код
use std::{fmt};
pub const MAX_ATTEMPTS: u8 = 5;
#[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 max_attempts: u8,
pub alphabet: String,
pub word: String,
pub guesses: Vec<String>,
}
#[derive(Debug)]
pub struct Word {
pub guess: Vec<char>,
pub correct_indexes: Vec<u32>,
pub contained_but_not_positioned: Vec<u32>
}
pub fn validate_word_str(alphabet: &str, word: &str) -> Result<(), GameError> {
for c in word.chars() {
if !alphabet.contains(c) {
return Err(GameError::NotInAlphabet(c))
}
}
return Ok(())
}
impl Word {
pub fn new(guess: &str, word: &str) -> Self {
if guess.len() != word.len() {
panic!("This shouldn't happen as checks are implemented elsewhere")
}
let mut index_vector: Vec<u32> = Vec::new();
let mut incorrectly_positioned: Vec<u32> = Vec::new();
let guess_vec: Vec<char> = guess.chars().collect();
let word_vec: Vec<char> = word.chars().collect();
for (i, c) in guess_vec.iter().enumerate() {
for (j, c2) in word_vec.iter().enumerate() {
if i == j && c == c2 {
index_vector.push(i as u32);
break;
} else {
if c == c2 {
/*
* Do this for duplicate letters. Going this way
* it's possible that there are some duplicate indexes
* in this vector, but we don't really care with the current use case.
* We could remove them but we will have to sort the vector
* and dedup and we don't really have to do that.
*/
if j < i {
if !index_vector.contains(&(j as u32)) {
incorrectly_positioned.push(i as u32);
}
} else {
if !(guess_vec[j] == *c2) {
incorrectly_positioned.push(i as u32);
}
}
}
}
}
}
Word {
guess: guess_vec,
correct_indexes: index_vector,
contained_but_not_positioned: incorrectly_positioned
}
}
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let validate = validate_word_str(alphabet, word);
match validate {
Err(e) => { return Err(e) }
_ => { return Ok(Game {status: GameStatus::InProgress,
attempts: 0,
max_attempts: MAX_ATTEMPTS,
word: word.to_string(),
alphabet: alphabet.to_string(),
guesses: Vec::new()})
}
}
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
if guess.len() != self.word.len() {
return Err(GameError::WrongLength { expected: (self.word.chars().count()),
actual: (guess.chars().count()) })
}
let validate = validate_word_str(self.alphabet.as_str(), guess);
match validate {
Err(e) => {return Err(e)}
_ => {
self.attempts += 1;
if guess == self.word {
self.status = GameStatus::Won;
}
self.guesses.push(guess.to_string());
if self.attempts >= MAX_ATTEMPTS {
self.status = GameStatus::Lost;
}
return Ok(Word::new(guess, self.word.as_str()))
}
}
}
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut res: String = String::from("");
let mut uppercased_guess: String = self.guess.clone().into_iter().collect();
uppercased_guess = uppercased_guess.to_uppercase();
for (i, c) in uppercased_guess.chars().enumerate() {
if self.correct_indexes.contains(&(i as u32)) {
res += format!("[{}]", c).as_str();
} else if self.contained_but_not_positioned.contains(&(i as u32)) {
res += format!("({})", c).as_str();
} else {
res += format!(">{}<", c).as_str();
}
}
write!(f, "{}", res)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut res: String = String::from("");
let mut i: usize = 0;
while i < self.word.chars().count() {
res += "|_|";
i += 1;
}
if self.attempts > 0 {
res += "\n";
for guess in self.guesses.clone() {
let word: Word = Word::new(guess.as_str(), self.word.as_str());
res += format!("{word}\n").as_str();
}
// remove last newline added
res.pop();
}
write!(f, "{}", res)
}
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20230111-3772066-1dvc24a/solution) Finished test [unoptimized + debuginfo] target(s) in 0.83s 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 ... FAILED test solution_test::test_game_state_1 ... FAILED test solution_test::test_game_state_2 ... FAILED 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_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_game_display_german stdout ---- thread 'solution_test::test_game_display_german' panicked at 'assertion failed: `(left == right)` left: `"|_||_||_|\n>F<[Ü][S]>S<"`, right: `"|_||_||_|\n>F<[Ü][SS]"`', tests/solution_test.rs:135:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ---- solution_test::test_game_state_1 stdout ---- thread 'solution_test::test_game_state_1' panicked at 'Expression Ok(Word { guess: ['a', 'b', 'c'], correct_indexes: [0, 1, 2], contained_but_not_positioned: [] }) does not match the pattern "Err(GameError::GameIsOver(GameStatus::Won))"', tests/solution_test.rs:146:5 ---- solution_test::test_game_state_2 stdout ---- thread 'solution_test::test_game_state_2' panicked at 'Expression Ok(Word { guess: ['a', 'b', 'c'], correct_indexes: [0, 1, 2], contained_but_not_positioned: [] }) does not match the pattern "Err(GameError::GameIsOver(GameStatus::Lost))"', tests/solution_test.rs:160:5 ---- solution_test::test_word_display_german stdout ---- thread 'solution_test::test_word_display_german' panicked at 'assertion failed: `(left == right)` left: `">F<[Ü][S]>S<"`, right: `">F<[Ü][SS]"`', tests/solution_test.rs:88: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: 4 }) does not match the pattern "Err(GameError::NotInAlphabet('х'))"', tests/solution_test.rs:46:5 failures: solution_test::test_game_display_german solution_test::test_game_state_1 solution_test::test_game_state_2 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`