Решение на Wordle от Христо Вълев

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

Към профила на Христо Вълев

Резултати

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

Код

use crate::GameStatus::{InProgress, Lost, Won};
use crate::Letter::FullMatch;
use std::fmt;
use std::fmt::{Debug, Formatter};
#[derive(Debug)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug, Clone)]
pub enum Letter {
Unknown(char),
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[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 answer: String,
pub attemptHistory: Vec<Word>,
pub gameAlphabet: String,
}
#[derive(Debug, Clone)]
pub struct Word {
pub word: Vec<Letter>,
}
// Проверява къде е дадена буква(ако изобщо я има) в отговора и return-ва дали е Partial или FullMatch (или NoMatch ако я няма)
pub fn letterMatch(c: char, index: usize, answer: &str) -> Letter {
let answerVec: Vec<char> = answer.chars().collect();
if !answer.contains(c) {
return Letter::NoMatch(c);
} else {
let mut counter = 0;
for ch in answerVec {
if counter == index && ch == c {
return Letter::FullMatch(c);
}
counter = counter + 1;
}
return Letter::PartialMatch(c); // Щом не сме return-нали до тук значи че присъства в думата но не на точното място => PartialMatch
}
}
// Генерира "нулевия опит" който е |_||_|...|_|
pub fn zerothAttempt(word: &str) -> Vec<Word> {
let mut letters: Vec<Letter> = vec![];
for c in word.chars() {
letters.push(Letter::Unknown(c));
}
let mut word: Word = Word { word: vec![] };
for letter in letters {
word.push(letter);
}
let result: Vec<Word> = vec![word];
return result;
}
impl Word {
// Push-ва Letter в думата, за да може като се изпринти да принти с дадените в условието скоби
pub fn push(&mut self, element: Letter) {
self.word.push(element);
}
// Проверява дали е позната думата
pub fn fullMatch(&mut self) -> bool {
for letter in &self.word {
let matches: bool = match letter {
FullMatch(_c) => true,
_ => false,
};
if !matches {
return false;
}
}
return true;
}
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let alphabetCharacters: Vec<char> = alphabet.chars().collect();
let wordCharacters: Vec<char> = word.chars().collect();
for c in wordCharacters {
let validCharacters: bool = alphabetCharacters.contains(&c); // става false ако буквата я няма в думата => не е валиден опит и ще return-не GameError::NotInAlphabet
if !validCharacters {
return Err(GameError::NotInAlphabet(c));
}
}
let _attemptHistory: Vec<Word> = zerothAttempt(word); // В нов игра това е посто |_||_|...|_|
let result = Game {
status: InProgress,
attempts: 0,
answer: word.parse().unwrap(),
attemptHistory: _attemptHistory,
gameAlphabet: alphabet.to_string(),
};
return Ok(result);
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
match self.status {
Won => {
return Err(GameError::GameIsOver(Won));
}
Lost => {
return Err(GameError::GameIsOver(Lost));
}
_ => (),
}
if guess.chars().count() != self.answer.chars().count() {
return Err(GameError::WrongLength {
expected: self.answer.chars().count(),
actual: guess.chars().count(),
});
}
let guessChars: Vec<char> = guess.chars().collect();
for c in &guessChars {
let validGuess = self.gameAlphabet.contains(*c);
if !validGuess {
return Err(GameError::NotInAlphabet(*c));
}
}
let mut wordRes: Word = Word { word: vec![] };
let mut index = 0;
for c in &guessChars {
wordRes.push(letterMatch(*c, index, &self.answer));
index = index + 1;
}
self.attemptHistory.push(wordRes.clone());
if wordRes.fullMatch() {
self.status = GameStatus::Won;
}
self.attempts = self.attempts + 1;
if self.attempts >= 5 {
self.status = GameStatus::Lost;
}
return Ok(wordRes);
}
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for letter in &self.word {
write!(f, "{}", letter).unwrap();
}
write!(f, "")
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut index: usize = 0;
for word in &self.attemptHistory {
if index < self.attemptHistory.len() - 1 {
write!(f, "{}\n", word).unwrap();
} else {
write!(f, "{}", word).unwrap(); // След последната дума не слагаме нов ред!!!
}
index = index + 1;
}
write!(f, "")
}
}
impl fmt::Display for Letter {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self {
Letter::Unknown(_c) => write!(f, "|_|"),
Letter::NoMatch(c) => write!(f, ">{}<", c.to_uppercase()),
Letter::PartialMatch(c) => write!(f, "({})", c.to_uppercase()),
Letter::FullMatch(c) => write!(f, "[{}]", c.to_uppercase()),
}
}
}

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

Compiling solution v0.1.0 (/tmp/d20230111-3772066-qpviqx/solution)
warning: structure field `attemptHistory` should have a snake case name
  --> src/lib.rs:33:9
   |
33 |     pub attemptHistory: Vec<Word>,
   |         ^^^^^^^^^^^^^^ help: convert the identifier to snake case: `attempt_history`
   |
   = note: `#[warn(non_snake_case)]` on by default

warning: structure field `gameAlphabet` should have a snake case name
  --> src/lib.rs:34:9
   |
34 |     pub gameAlphabet: String,
   |         ^^^^^^^^^^^^ help: convert the identifier to snake case: `game_alphabet`

warning: function `letterMatch` should have a snake case name
  --> src/lib.rs:43:8
   |
43 | pub fn letterMatch(c: char, index: usize, answer: &str) -> Letter {
   |        ^^^^^^^^^^^ help: convert the identifier to snake case: `letter_match`

warning: variable `answerVec` should have a snake case name
  --> src/lib.rs:44:9
   |
44 |     let answerVec: Vec<char> = answer.chars().collect();
   |         ^^^^^^^^^ help: convert the identifier to snake case: `answer_vec`

warning: function `zerothAttempt` should have a snake case name
  --> src/lib.rs:60:8
   |
60 | pub fn zerothAttempt(word: &str) -> Vec<Word> {
   |        ^^^^^^^^^^^^^ help: convert the identifier to snake case: `zeroth_attempt`

warning: method `fullMatch` should have a snake case name
  --> src/lib.rs:80:12
   |
80 |     pub fn fullMatch(&mut self) -> bool {
   |            ^^^^^^^^^ help: convert the identifier to snake case: `full_match`

warning: variable `alphabetCharacters` should have a snake case name
  --> src/lib.rs:96:13
   |
96 |         let alphabetCharacters: Vec<char> = alphabet.chars().collect();
   |             ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `alphabet_characters`

warning: variable `wordCharacters` should have a snake case name
  --> src/lib.rs:97:13
   |
97 |         let wordCharacters: Vec<char> = word.chars().collect();
   |             ^^^^^^^^^^^^^^ help: convert the identifier to snake case: `word_characters`

warning: variable `validCharacters` should have a snake case name
   --> src/lib.rs:100:17
    |
100 | ...   let validCharacters: bool = alphabetCharacters.contains(&c); // става false ако буквата я няма в думата => не е валиден опит и ще r...
    |           ^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `valid_characters`

warning: variable `_attemptHistory` should have a snake case name
   --> src/lib.rs:106:13
    |
106 |         let _attemptHistory: Vec<Word> = zerothAttempt(word); // В нов игра това е посто |_||_|...|_|
    |             ^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `_attempt_history`

warning: variable `guessChars` should have a snake case name
   --> src/lib.rs:135:13
    |
135 |         let guessChars: Vec<char> = guess.chars().collect();
    |             ^^^^^^^^^^ help: convert the identifier to snake case: `guess_chars`

warning: variable `validGuess` should have a snake case name
   --> src/lib.rs:137:17
    |
137 |             let validGuess = self.gameAlphabet.contains(*c);
    |                 ^^^^^^^^^^ help: convert the identifier to snake case: `valid_guess`

warning: variable `wordRes` should have a snake case name
   --> src/lib.rs:143:17
    |
143 |         let mut wordRes: Word = Word { word: vec![] };
    |                 ^^^^^^^ help: convert the identifier to snake case: `word_res`

warning: `solution` (lib) generated 13 warnings
    Finished test [unoptimized + debuginfo] target(s) in 0.84s
     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_3 ... ok
test solution_test::test_game_state_2 ... ok
test solution_test::test_word_display ... ok
test solution_test::test_word_display_german ... ok
test solution_test::test_word_display_bulgarian ... ok
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_word_not_in_alphabet_on_guess_cyrillic ... ok
test solution_test::test_wrong_length ... ok

test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

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

Христо качи първо решение на 22.11.2022 17:56 (преди почти 3 години)

Христо качи решение на 22.11.2022 17:57 (преди почти 3 години)

-#![allow(non_snake_case)]
-
use crate::GameStatus::{InProgress, Lost, Won};
use crate::Letter::FullMatch;
use std::fmt;
use std::fmt::{Debug, Formatter};
#[derive(Debug)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug, Clone)]
pub enum Letter {
Unknown(char),
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[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 answer: String,
pub attemptHistory: Vec<Word>,
pub gameAlphabet: String,
}
#[derive(Debug, Clone)]
pub struct Word {
pub word: Vec<Letter>,
}
// Проверява къде е дадена буква(ако изобщо я има) в отговора и return-ва дали е Partial или FullMatch (или NoMatch ако я няма)
pub fn letterMatch(c: char, index: usize, answer: &str) -> Letter {
let answerVec: Vec<char> = answer.chars().collect();
if !answer.contains(c) {
return Letter::NoMatch(c);
} else {
let mut counter = 0;
for ch in answerVec {
if counter == index && ch == c {
return Letter::FullMatch(c);
}
counter = counter + 1;
}
return Letter::PartialMatch(c); // Щом не сме return-нали до тук значи че присъства в думата но не на точното място => PartialMatch
}
}
// Генерира "нулевия опит" който е |_||_|...|_|
pub fn zerothAttempt(word: &str) -> Vec<Word> {
let mut letters: Vec<Letter> = vec![];
for c in word.chars() {
letters.push(Letter::Unknown(c));
}
let mut word: Word = Word { word: vec![] };
for letter in letters {
word.push(letter);
}
let result: Vec<Word> = vec![word];
return result;
}
impl Word {
// Push-ва Letter в думата, за да може като се изпринти да принти с дадените в условието скоби
pub fn push(&mut self, element: Letter) {
self.word.push(element);
}
// Проверява дали е позната думата
pub fn fullMatch(&mut self) -> bool {
for letter in &self.word {
let matches: bool = match letter {
FullMatch(_c) => true,
_ => false,
};
if !matches {
return false;
}
}
return true;
}
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let alphabetCharacters: Vec<char> = alphabet.chars().collect();
let wordCharacters: Vec<char> = word.chars().collect();
for c in wordCharacters {
let validCharacters: bool = alphabetCharacters.contains(&c); // става false ако буквата я няма в думата => не е валиден опит и ще return-не GameError::NotInAlphabet
if !validCharacters {
return Err(GameError::NotInAlphabet(c));
}
}
let _attemptHistory: Vec<Word> = zerothAttempt(word); // В нов игра това е посто |_||_|...|_|
let result = Game {
status: InProgress,
attempts: 0,
answer: word.parse().unwrap(),
attemptHistory: _attemptHistory,
gameAlphabet: alphabet.to_string(),
};
return Ok(result);
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
match self.status {
Won => {
return Err(GameError::GameIsOver(Won));
}
Lost => {
return Err(GameError::GameIsOver(Lost));
}
_ => (),
}
if guess.chars().count() != self.answer.chars().count() {
return Err(GameError::WrongLength {
expected: self.answer.chars().count(),
actual: guess.chars().count(),
});
}
let guessChars: Vec<char> = guess.chars().collect();
for c in &guessChars {
let validGuess = self.gameAlphabet.contains(*c);
if !validGuess {
return Err(GameError::NotInAlphabet(*c));
}
}
let mut wordRes: Word = Word { word: vec![] };
let mut index = 0;
for c in &guessChars {
wordRes.push(letterMatch(*c, index, &self.answer));
index = index + 1;
}
self.attemptHistory.push(wordRes.clone());
if wordRes.fullMatch() {
self.status = GameStatus::Won;
}
self.attempts = self.attempts + 1;
if self.attempts >= 5 {
self.status = GameStatus::Lost;
}
return Ok(wordRes);
}
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for letter in &self.word {
write!(f, "{}", letter).unwrap();
}
write!(f, "")
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut index: usize = 0;
for word in &self.attemptHistory {
if index < self.attemptHistory.len() - 1 {
write!(f, "{}\n", word).unwrap();
} else {
write!(f, "{}", word).unwrap(); // След последната дума не слагаме нов ред!!!
}
index = index + 1;
}
write!(f, "")
}
}
impl fmt::Display for Letter {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match *self {
Letter::Unknown(_c) => write!(f, "|_|"),
Letter::NoMatch(c) => write!(f, ">{}<", c.to_uppercase()),
Letter::PartialMatch(c) => write!(f, "({})", c.to_uppercase()),
Letter::FullMatch(c) => write!(f, "[{}]", c.to_uppercase()),
}
}
}