Решение на 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: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()),
}
}
}