Решение на Wordle от Ива Манчевска
Резултати
- 16 точки от тестове
- 0 бонус точки
- 16 точки общо
- 12 успешни тест(а)
- 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 wordToGuess: String,
pub alphabet: String,
pub words: Vec<Word>,
}
#[derive(Debug)]
pub struct Word {
pub guess: String,
pub letters: Vec<Letter>,
}
#[derive(Debug,Clone)]
pub enum Letter {
Unknown(char),
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
for c in word.chars() {
if alphabet.find(c)==None{
return Err(GameError::NotInAlphabet(c))
}
}
let mut letters = Vec::<Letter>::new();
for i in 1..word.chars().count()+1{
letters.push(Letter::Unknown('_'))
}
Ok(Game{
status: GameStatus::InProgress,
attempts: 0,
wordToGuess: word.to_string().to_uppercase(),
alphabet: alphabet.to_string().to_uppercase(),
words: vec![Word{guess:"".to_string(), letters: letters}]
})
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
if matches!(self.status, GameStatus::Won){
return Err(GameError::GameIsOver(GameStatus::Won))
}
if matches!(self.status, GameStatus::Lost){
return Err(GameError::GameIsOver(GameStatus::Lost))
}
if guess.to_uppercase().chars().count() != self.wordToGuess.to_uppercase().chars().count(){
return Err(GameError::WrongLength{
expected: self.wordToGuess.to_uppercase().chars().count(),
actual: guess.to_uppercase().chars().count(),
})
}
for c in guess.to_uppercase().chars() {
if !self.alphabet.contains(c){
return Err(GameError::NotInAlphabet(c))
}
}
let mut mainWord = &self.wordToGuess;
let mut letters = Vec::<Letter>::new();
let mut fullMatches=0;
for (i,c) in guess.to_uppercase().chars().enumerate() {
if c == mainWord.chars().nth(i).unwrap(){
fullMatches += 1;
letters.push(Letter::FullMatch(c))
}else{
if mainWord.contains(c){
letters.push(Letter::PartialMatch(c))
}else{
letters.push(Letter::NoMatch(c))
}
}
if fullMatches==mainWord.chars().count(){
let mut newStatus = GameStatus::Won;
std::mem::swap(&mut self.status, &mut newStatus);
}
}
self.attempts += 1;
if self.attempts == 5{
let mut newStatus = GameStatus::Lost;
std::mem::swap(&mut self.status, &mut newStatus);
}
self.words.push( Word{
guess: guess.to_string(),
letters: letters.to_vec(),
});
return Ok(Word{
guess: guess.to_string(),
letters: letters.to_vec(),
})
}
}
use std::fmt;
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
self.letters.iter().map(|l| {
match l{
Letter::Unknown(x) => write!(f, "|{}|", x),
Letter::FullMatch(x) => write!(f,"[{}]",x.to_uppercase()),
Letter::PartialMatch(x) => write!(f,"({})",x.to_uppercase()),
Letter::NoMatch(x) => write!(f,">{}<",x.to_uppercase()),
}
}).collect()
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let count = self.words.iter().count();
self.words.iter().enumerate().map(|(i,w)|{
if i < count-1{
write!(f, "{}\n", w)
}else{
write!(f, "{}", w)
}
}).collect()
}
}
#[cfg(test)]
#[test]
fn test_basic() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
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]");
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20230111-3772066-jndfcy/solution) warning: unused variable: `i` --> src/lib.rs:46:13 | 46 | for i in 1..word.chars().count()+1{ | ^ help: if this is intentional, prefix it with an underscore: `_i` | = note: `#[warn(unused_variables)]` on by default warning: variable does not need to be mutable --> src/lib.rs:78:17 | 78 | let mut mainWord = &self.wordToGuess; | ----^^^^^^^^ | | | help: remove this `mut` | = note: `#[warn(unused_mut)]` on by default warning: structure field `wordToGuess` should have a snake case name --> src/lib.rs:19:9 | 19 | pub wordToGuess: String, | ^^^^^^^^^^^ help: convert the identifier to snake case: `word_to_guess` | = note: `#[warn(non_snake_case)]` on by default warning: variable `mainWord` should have a snake case name --> src/lib.rs:78:21 | 78 | let mut mainWord = &self.wordToGuess; | ^^^^^^^^ help: convert the identifier to snake case: `main_word` warning: variable `fullMatches` should have a snake case name --> src/lib.rs:80:21 | 80 | let mut fullMatches=0; | ^^^^^^^^^^^ help: convert the identifier to snake case: `full_matches` warning: variable `newStatus` should have a snake case name --> src/lib.rs:93:29 | 93 | let mut newStatus = GameStatus::Won; | ^^^^^^^^^ help: convert the identifier to snake case: `new_status` warning: variable `newStatus` should have a snake case name --> src/lib.rs:99:25 | 99 | let mut newStatus = GameStatus::Lost; | ^^^^^^^^^ help: convert the identifier to snake case: `new_status` warning: `solution` (lib) generated 7 warnings Finished test [unoptimized + debuginfo] target(s) in 0.86s 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 ... FAILED 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 ... 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_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_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(NotInAlphabet('Х')) does not match the pattern "Err(GameError::NotInAlphabet('х'))"', tests/solution_test.rs:46:5 failures: solution_test::test_game_display_german solution_test::test_word_display_german solution_test::test_word_not_in_alphabet_on_guess_cyrillic test result: FAILED. 12 passed; 3 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 16:56 (преди почти 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 wordToGuess: String,
pub alphabet: String,
pub words: Vec<Word>,
}
#[derive(Debug)]
pub struct Word {
pub guess: String,
pub letters: Vec<Letter>,
}
#[derive(Debug,Clone)]
pub enum Letter {
Unknown(char),
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
for c in word.chars() {
if alphabet.find(c)==None{
return Err(GameError::NotInAlphabet(c))
}
}
let mut letters = Vec::<Letter>::new();
for i in 1..word.chars().count()+1{
letters.push(Letter::Unknown('_'))
}
Ok(Game{
status: GameStatus::InProgress,
attempts: 0,
wordToGuess: word.to_string().to_uppercase(),
alphabet: alphabet.to_string().to_uppercase(),
words: vec![Word{guess:"".to_string(), letters: letters}]
})
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
if matches!(self.status, GameStatus::Won){
return Err(GameError::GameIsOver(GameStatus::Won))
}
if matches!(self.status, GameStatus::Lost){
return Err(GameError::GameIsOver(GameStatus::Lost))
}
- if guess.chars().count() != self.wordToGuess.chars().count(){
+ if guess.to_uppercase().chars().count() != self.wordToGuess.to_uppercase().chars().count(){
return Err(GameError::WrongLength{
- expected: self.wordToGuess.chars().count(),
- actual: guess.chars().count(),
+ expected: self.wordToGuess.to_uppercase().chars().count(),
+ actual: guess.to_uppercase().chars().count(),
})
}
for c in guess.to_uppercase().chars() {
if !self.alphabet.contains(c){
return Err(GameError::NotInAlphabet(c))
}
}
let mut mainWord = &self.wordToGuess;
let mut letters = Vec::<Letter>::new();
let mut fullMatches=0;
for (i,c) in guess.to_uppercase().chars().enumerate() {
if c == mainWord.chars().nth(i).unwrap(){
fullMatches += 1;
letters.push(Letter::FullMatch(c))
}else{
if mainWord.contains(c){
letters.push(Letter::PartialMatch(c))
}else{
letters.push(Letter::NoMatch(c))
}
}
if fullMatches==mainWord.chars().count(){
let mut newStatus = GameStatus::Won;
std::mem::swap(&mut self.status, &mut newStatus);
}
}
self.attempts += 1;
if self.attempts == 5{
let mut newStatus = GameStatus::Lost;
std::mem::swap(&mut self.status, &mut newStatus);
}
self.words.push( Word{
guess: guess.to_string(),
letters: letters.to_vec(),
});
return Ok(Word{
guess: guess.to_string(),
letters: letters.to_vec(),
})
}
}
use std::fmt;
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
self.letters.iter().map(|l| {
match l{
Letter::Unknown(x) => write!(f, "|{}|", x),
Letter::FullMatch(x) => write!(f,"[{}]",x.to_uppercase()),
Letter::PartialMatch(x) => write!(f,"({})",x.to_uppercase()),
Letter::NoMatch(x) => write!(f,">{}<",x.to_uppercase()),
}
}).collect()
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let count = self.words.iter().count();
self.words.iter().enumerate().map(|(i,w)|{
if i < count-1{
write!(f, "{}\n", w)
}else{
write!(f, "{}", w)
}
}).collect()
}
}
#[cfg(test)]
#[test]
fn test_basic() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
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]");
-}
-
-fn main(){
-
}