Решение на Hangman от Иван Иванов

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

Към профила на Иван Иванов

Резултати

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

Код

/// Very alpha-alpha solution... not sure if I'll have time to finish
#[derive(Debug)]
pub enum GameError {
ParseError(String),
BadGuess(String),
InvalidSolution(String),
GameOver,
}
impl Display for GameError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Something bad went wrong..." )
}
}
use std::str::FromStr;
#[derive(Debug)]
pub enum Command {
TryLetter(char),
TryWord(String),
Info,
Help,
Quit,
}
impl FromStr for Command {
type Err = GameError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let words: Vec<&str> = s.split_whitespace().collect();
let words: Vec<String> = words.iter().map(|x| x.to_lowercase()).collect();
let command_name = &words[0];
if "" == command_name {
Err(GameError::ParseError(String::from("Empty string is not a command")))
} else if "help" == command_name {
Ok(Command::Help)
} else if "info" == command_name {
Ok(Command::Info)
} else if "quit" == command_name {
Ok(Command::Quit)
} else if words.len() < 3 {
Err(GameError::ParseError(String::from("Invalid comand")))
} else {
if "try".starts_with(&words[0]) && "letter".starts_with(&words[1]) {
if words[2].len() != 1 {
Err(GameError::ParseError(String::from("Passed more than one letter to 'try letter'")))
} else {
Ok(Command::TryLetter(words[2].chars().nth(0).unwrap()))
}
} else if "try".starts_with(&words[0]) && "word".starts_with(&words[1]) {
Ok(Command::TryWord(words[2].clone()))
} else {
Err(GameError::ParseError(String::from("Invalid command")))
}
}
}
}
use std::collections::HashSet;
#[derive(Debug)]
pub struct Game {
pub attempted_letters: HashSet<char>,
pub attempted_words: HashSet<String>,
pub attempts_remaining: u32,
solution: String,
current_solution: String,
is_over: bool,
}
impl Game {
pub fn new(solution: &str, attempts: u32) -> Result<Self, GameError> {
if validate_input(solution) {
Ok(Self{
attempted_letters: HashSet::new(),
attempted_words: HashSet::new(),
attempts_remaining: attempts,
solution: String::from(solution.trim()),
current_solution: std::iter::repeat("_").take(solution.len()).collect::<String>(),
is_over: false,
})
} else {
Err(GameError::InvalidSolution(String::from("Solution not valid")))
}
}
}
pub fn validate_input(solution: &str) -> bool {
if solution == "" {
false
} else if str_contains_nonalpha(solution) {
false
} else {
true
}
}
pub fn str_contains_nonalpha(solution: &str) -> bool {
let mut contains = false;
for i in solution.chars() {
if !i.is_alphabetic() {
contains = true;
}
}
contains
}
impl Game {
pub fn guess_letter(&mut self, guess: char) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
Err(GameError::GameOver)
} else if self.attempted_letters.contains(&guess) {
Err(GameError::BadGuess(String::from("Attempted letter already tried.")))
} else {
self.attempted_letters.insert(guess);
self.attempts_remaining = self.attempts_remaining - 1;
let mut new_current: String = String::new();
let mut is_contained: bool = false;
for (x, y) in self.solution.chars().zip(self.current_solution.chars()) {
if guess == x {
is_contained = true;
new_current.push(guess);
} else {
new_current.push(y);
}
}
self.current_solution = new_current;
if self.current_solution == self.solution {
self.is_over = true;
Ok(true)
} else if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(is_contained)
}
}
}
pub fn guess_word(&mut self, guess: &str) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
self.is_over = true;
Err(GameError::GameOver)
} else if self.attempted_words.contains(guess){
Err(GameError::BadGuess(String::from("Attempted word already tried")))
} else if self.solution == guess {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
self.is_over = true;
self.current_solution = String::from(guess);
Ok(true)
} else {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(false)
}
}
}
pub fn is_over(&self) -> bool {
self.is_over
}
}
use std::fmt::{self, Display};
impl Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.current_solution == self.solution {
write!(
f,
"You won! The correct word is {}",
self.solution
)
} else {
write!(
f,
"{}",
separate_by_whitespace(&self.current_solution))
}
}
}
fn separate_by_whitespace(word: &str) -> String {
let mut s = String::new();
for ch in word.chars(){
s.push(ch);
s.push(' ');
}
let s: String = String::from(s.trim_left());
s
}

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

Compiling solution v0.1.0 (file:///tmp/d20171210-6053-2tonk1/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 6.23 secs
     Running target/debug/deps/solution-3f98bfa5c86a5dd9

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-3d9e4ea2eafbbc82

running 15 tests
test solution_test::test_command_parsing_cyrillic ... FAILED
test solution_test::test_command_parsing_extra_stuff ... ok
test solution_test::test_command_parsing_full_words ... ok
test solution_test::test_command_parsing_partial_words ... FAILED
test solution_test::test_command_parsing_spacing ... FAILED
test solution_test::test_command_parsing_special ... FAILED
test solution_test::test_game_basic ... ok
test solution_test::test_game_cyrillic ... ok
test solution_test::test_game_display ... ok
test solution_test::test_game_error ... ok
test solution_test::test_game_guess_basic ... FAILED
test solution_test::test_game_guess_state_lose ... FAILED
test solution_test::test_game_guess_state_won ... FAILED
test solution_test::test_game_guess_word ... FAILED
test solution_test::test_game_over_guesses ... FAILED

failures:

---- solution_test::test_command_parsing_cyrillic stdout ----
	thread 'solution_test::test_command_parsing_cyrillic' panicked at 'Expected Ok(Command::TryLetter('\u{44f}')) to match Err(ParseError("Passed more than one letter to \'try letter\'"))', tests/solution_test.rs:235:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.

---- solution_test::test_command_parsing_partial_words stdout ----
	thread 'solution_test::test_command_parsing_partial_words' panicked at 'Expected Ok(Command::Quit) to match Err(ParseError("Invalid comand"))', tests/solution_test.rs:205:4

---- solution_test::test_command_parsing_spacing stdout ----
	thread 'solution_test::test_command_parsing_spacing' panicked at 'Expected Ok(Command::Quit) to match Err(ParseError("Invalid comand"))', tests/solution_test.rs:230:4

---- solution_test::test_command_parsing_special stdout ----
	thread 'solution_test::test_command_parsing_special' panicked at 'Expected Ok(Command::TryLetter('\u{44f}')) to match Err(ParseError("Passed more than one letter to \'try letter\'"))', tests/solution_test.rs:194:4

---- solution_test::test_game_guess_basic stdout ----
	thread 'solution_test::test_game_guess_basic' panicked at 'assertion failed: `(left == right)`
  left: `10`,
 right: `9`', tests/solution_test.rs:84:4

---- solution_test::test_game_guess_state_lose stdout ----
	thread 'solution_test::test_game_guess_state_lose' panicked at 'assertion failed: `(left == right)`
  left: `true`,
 right: `false`', tests/solution_test.rs:126:4

---- solution_test::test_game_guess_state_won stdout ----
	thread 'solution_test::test_game_guess_state_won' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`', tests/solution_test.rs:143:4

---- solution_test::test_game_guess_word stdout ----
	thread 'solution_test::test_game_guess_word' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `0`', tests/solution_test.rs:112:4

---- solution_test::test_game_over_guesses stdout ----
	thread 'solution_test::test_game_over_guesses' panicked at 'Expected Err(GameError::GameOver) to match Err(BadGuess("Attempted letter already tried."))', tests/solution_test.rs:157:4


failures:
    solution_test::test_command_parsing_cyrillic
    solution_test::test_command_parsing_partial_words
    solution_test::test_command_parsing_spacing
    solution_test::test_command_parsing_special
    solution_test::test_game_guess_basic
    solution_test::test_game_guess_state_lose
    solution_test::test_game_guess_state_won
    solution_test::test_game_guess_word
    solution_test::test_game_over_guesses

test result: FAILED. 6 passed; 9 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'

История (4 версии и 5 коментара)

Иван качи първо решение на 06.12.2017 01:04 (преди почти 8 години)

Иван качи решение на 06.12.2017 10:27 (преди почти 8 години)

/// Very alpha-alpha solution... not sure if I'll have time to finish
#[derive(Debug)]
pub enum GameError {
ParseError(String),
BadGuess(String),
InvalidSolution(String),
GameOver,
}
impl Display for GameError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Something bad went wrong..." )
}
}
use std::str::FromStr;
#[derive(Debug)]
pub enum Command {
TryLetter(char),
TryWord(String),
Info,
Help,
Quit,
}
impl FromStr for Command {
type Err = GameError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let words: Vec<&str> = s.split_whitespace().collect();
let words: Vec<String> = words.iter().map(|x| x.to_lowercase()).collect();
let command_name = &words[0];
if "help" == command_name {
Ok(Command::Help)
} else if "info" == command_name {
Ok(Command::Info)
} else if "quit" == command_name {
Ok(Command::Quit)
} else if words.len() < 3 {
Err(GameError::ParseError(String::from("Invalid comand")))
} else {
if "try".starts_with(&words[0]) && "letter".starts_with(&words[1]) {
Ok(Command::TryLetter(words[2].chars().nth(0).unwrap()))
} else if "try".starts_with(&words[0]) && "word".starts_with(&words[1]) {
Ok(Command::TryWord(words[2].clone()))
} else {
Err(GameError::ParseError(String::from("Invalid command")))
}
}
}
}
use std::collections::HashSet;
pub struct Game {
pub attempted_letters: HashSet<char>,
pub attempted_words: HashSet<String>,
pub attempts_remaining: u32,
solution: String,
current_solution: String,
is_over: bool,
}
impl Game {
pub fn new(solution: &str, attempts: u32) -> Result<Self, GameError> {
Ok(Self{
attempted_letters: HashSet::new(),
attempted_words: HashSet::new(),
attempts_remaining: attempts,
solution: String::from(solution),
current_solution: std::iter::repeat("_").take(solution.len()).collect::<String>(),
is_over: false,
})
}
}
impl Game {
pub fn guess_letter(&mut self, guess: char) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
Err(GameError::GameOver)
} else if self.attempted_letters.contains(&guess) {
Err(GameError::BadGuess(String::from("Attempted letter already tried.")))
} else {
self.attempted_letters.insert(guess);
self.attempts_remaining = self.attempts_remaining - 1;
let mut new_current: String = String::new();
let mut is_contained: bool = false;
for (x, y) in self.solution.chars().zip(self.current_solution.chars()) {
if guess == x {
is_contained = true;
new_current.push(guess);
} else {
new_current.push(y);
}
}
self.current_solution = new_current;
if self.current_solution == self.solution {
self.is_over = true;
Ok(true)
} else if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(is_contained)
}
}
}
pub fn guess_word(&mut self, guess: &str) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
self.is_over = true;
Err(GameError::GameOver)
} else if self.attempted_words.contains(guess){
Err(GameError::BadGuess(String::from("Attempted word already tried")))
} else if self.solution == guess {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
self.is_over = true;
self.current_solution = String::from(guess);
Ok(true)
} else {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(false)
}
}
}
pub fn is_over(&self) -> bool {
self.is_over
}
}
-use std::fmt::{self, Display, Write};
+use std::fmt::{self, Display};
impl Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.current_solution == self.solution {
write!(
f,
"You won! The correct word is {}",
self.solution
)
} else {
write!(
f,
"{}",
separate_by_whitespace(&self.current_solution))
}
}
}
fn separate_by_whitespace(word: &str) -> String {
let mut s = String::new();
for ch in word.chars(){
s.push(ch);
s.push(' ');
}
let s: String = String::from(s.trim_left());
s
}

Иван качи решение на 07.12.2017 22:53 (преди почти 8 години)

/// Very alpha-alpha solution... not sure if I'll have time to finish
#[derive(Debug)]
pub enum GameError {
ParseError(String),
BadGuess(String),
InvalidSolution(String),
GameOver,
}
impl Display for GameError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Something bad went wrong..." )
}
}
use std::str::FromStr;
#[derive(Debug)]
pub enum Command {
TryLetter(char),
TryWord(String),
Info,
Help,
Quit,
}
impl FromStr for Command {
type Err = GameError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let words: Vec<&str> = s.split_whitespace().collect();
let words: Vec<String> = words.iter().map(|x| x.to_lowercase()).collect();
let command_name = &words[0];
if "help" == command_name {
Ok(Command::Help)
} else if "info" == command_name {
Ok(Command::Info)
} else if "quit" == command_name {
Ok(Command::Quit)
} else if words.len() < 3 {
Err(GameError::ParseError(String::from("Invalid comand")))
} else {
if "try".starts_with(&words[0]) && "letter".starts_with(&words[1]) {
- Ok(Command::TryLetter(words[2].chars().nth(0).unwrap()))
+ if words[2].len() != 1 {
+ Err(GameError::ParseError(String::from("Passed more than one letter to 'try letter'")))
+ } else {
+ Ok(Command::TryLetter(words[2].chars().nth(0).unwrap()))
+ }
} else if "try".starts_with(&words[0]) && "word".starts_with(&words[1]) {
Ok(Command::TryWord(words[2].clone()))
} else {
Err(GameError::ParseError(String::from("Invalid command")))
}
}
}
}
use std::collections::HashSet;
+#[derive(Debug)]
pub struct Game {
pub attempted_letters: HashSet<char>,
pub attempted_words: HashSet<String>,
pub attempts_remaining: u32,
solution: String,
current_solution: String,
is_over: bool,
}
impl Game {
pub fn new(solution: &str, attempts: u32) -> Result<Self, GameError> {
- Ok(Self{
- attempted_letters: HashSet::new(),
- attempted_words: HashSet::new(),
- attempts_remaining: attempts,
- solution: String::from(solution),
- current_solution: std::iter::repeat("_").take(solution.len()).collect::<String>(),
- is_over: false,
- })
+ if validate_input(solution) {
+ Ok(Self{
+ attempted_letters: HashSet::new(),
+ attempted_words: HashSet::new(),
+ attempts_remaining: attempts,
+ solution: String::from(solution.trim()),
+ current_solution: std::iter::repeat("_").take(solution.len()).collect::<String>(),
+ is_over: false,
+ })
+ } else {
+ Err(GameError::InvalidSolution(String::from("Solution not valid")))
+ }
}
+}
+
+pub fn validate_input(solution: &str) -> bool {
+ if solution == "" {
+ false
+ } else if str_contains_nonalpha(solution) {
+ false
+ } else {
+ true
+ }
+}
+pub fn str_contains_nonalpha(solution: &str) -> bool {
+ let mut contains = false;
+ for i in solution.chars() {
+ if !i.is_alphabetic() {
+ contains = true;
+ }
+ }
+ contains
}
impl Game {
pub fn guess_letter(&mut self, guess: char) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
Err(GameError::GameOver)
} else if self.attempted_letters.contains(&guess) {
Err(GameError::BadGuess(String::from("Attempted letter already tried.")))
} else {
self.attempted_letters.insert(guess);
self.attempts_remaining = self.attempts_remaining - 1;
let mut new_current: String = String::new();
let mut is_contained: bool = false;
for (x, y) in self.solution.chars().zip(self.current_solution.chars()) {
if guess == x {
is_contained = true;
new_current.push(guess);
} else {
new_current.push(y);
}
}
self.current_solution = new_current;
if self.current_solution == self.solution {
self.is_over = true;
Ok(true)
} else if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(is_contained)
}
}
}
pub fn guess_word(&mut self, guess: &str) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
self.is_over = true;
Err(GameError::GameOver)
} else if self.attempted_words.contains(guess){
Err(GameError::BadGuess(String::from("Attempted word already tried")))
} else if self.solution == guess {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
self.is_over = true;
self.current_solution = String::from(guess);
Ok(true)
} else {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(false)
}
}
}
pub fn is_over(&self) -> bool {
self.is_over
}
}
use std::fmt::{self, Display};
impl Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.current_solution == self.solution {
write!(
f,
"You won! The correct word is {}",
self.solution
)
} else {
write!(
f,
"{}",
separate_by_whitespace(&self.current_solution))
}
}
}
fn separate_by_whitespace(word: &str) -> String {
let mut s = String::new();
for ch in word.chars(){
s.push(ch);
s.push(' ');
}
let s: String = String::from(s.trim_left());
s
}

Иван качи решение на 07.12.2017 23:08 (преди почти 8 години)

/// Very alpha-alpha solution... not sure if I'll have time to finish
#[derive(Debug)]
pub enum GameError {
ParseError(String),
BadGuess(String),
InvalidSolution(String),
GameOver,
}
impl Display for GameError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Something bad went wrong..." )
}
}
use std::str::FromStr;
#[derive(Debug)]
pub enum Command {
TryLetter(char),
TryWord(String),
Info,
Help,
Quit,
}
impl FromStr for Command {
type Err = GameError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let words: Vec<&str> = s.split_whitespace().collect();
let words: Vec<String> = words.iter().map(|x| x.to_lowercase()).collect();
let command_name = &words[0];
- if "help" == command_name {
+ if "" == command_name {
+ Err(GameError::ParseError(String::from("Empty string is not a command")))
+ } else if "help" == command_name {
Ok(Command::Help)
} else if "info" == command_name {
Ok(Command::Info)
} else if "quit" == command_name {
Ok(Command::Quit)
} else if words.len() < 3 {
Err(GameError::ParseError(String::from("Invalid comand")))
} else {
if "try".starts_with(&words[0]) && "letter".starts_with(&words[1]) {
if words[2].len() != 1 {
Err(GameError::ParseError(String::from("Passed more than one letter to 'try letter'")))
} else {
Ok(Command::TryLetter(words[2].chars().nth(0).unwrap()))
}
} else if "try".starts_with(&words[0]) && "word".starts_with(&words[1]) {
Ok(Command::TryWord(words[2].clone()))
} else {
Err(GameError::ParseError(String::from("Invalid command")))
}
}
}
}
use std::collections::HashSet;
#[derive(Debug)]
pub struct Game {
pub attempted_letters: HashSet<char>,
pub attempted_words: HashSet<String>,
pub attempts_remaining: u32,
solution: String,
current_solution: String,
is_over: bool,
}
impl Game {
pub fn new(solution: &str, attempts: u32) -> Result<Self, GameError> {
if validate_input(solution) {
Ok(Self{
attempted_letters: HashSet::new(),
attempted_words: HashSet::new(),
attempts_remaining: attempts,
solution: String::from(solution.trim()),
current_solution: std::iter::repeat("_").take(solution.len()).collect::<String>(),
is_over: false,
})
} else {
Err(GameError::InvalidSolution(String::from("Solution not valid")))
}
}
}
pub fn validate_input(solution: &str) -> bool {
if solution == "" {
false
} else if str_contains_nonalpha(solution) {
false
} else {
true
}
}
pub fn str_contains_nonalpha(solution: &str) -> bool {
let mut contains = false;
for i in solution.chars() {
if !i.is_alphabetic() {
contains = true;
}
}
contains
}
impl Game {
pub fn guess_letter(&mut self, guess: char) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
Err(GameError::GameOver)
} else if self.attempted_letters.contains(&guess) {
Err(GameError::BadGuess(String::from("Attempted letter already tried.")))
} else {
self.attempted_letters.insert(guess);
self.attempts_remaining = self.attempts_remaining - 1;
let mut new_current: String = String::new();
let mut is_contained: bool = false;
for (x, y) in self.solution.chars().zip(self.current_solution.chars()) {
if guess == x {
is_contained = true;
new_current.push(guess);
} else {
new_current.push(y);
}
}
self.current_solution = new_current;
if self.current_solution == self.solution {
self.is_over = true;
Ok(true)
} else if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(is_contained)
}
}
}
pub fn guess_word(&mut self, guess: &str) -> Result<bool, GameError> {
if 0 == self.attempts_remaining {
self.is_over = true;
Err(GameError::GameOver)
} else if self.attempted_words.contains(guess){
Err(GameError::BadGuess(String::from("Attempted word already tried")))
} else if self.solution == guess {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
self.is_over = true;
self.current_solution = String::from(guess);
Ok(true)
} else {
self.attempted_words.insert(String::from(guess));
self.attempts_remaining = self.attempts_remaining - 1;
if 0 == self.attempts_remaining{
Err(GameError::GameOver)
} else {
Ok(false)
}
}
}
pub fn is_over(&self) -> bool {
self.is_over
}
}
use std::fmt::{self, Display};
impl Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.current_solution == self.solution {
write!(
f,
"You won! The correct word is {}",
self.solution
)
} else {
write!(
f,
"{}",
separate_by_whitespace(&self.current_solution))
}
}
}
fn separate_by_whitespace(word: &str) -> String {
let mut s = String::new();
for ch in word.chars(){
s.push(ch);
s.push(' ');
}
let s: String = String::from(s.trim_left());
s
}