RosettaCodeData/Task/Bulls-and-cows/Rust/bulls-and-cows.rust
2023-07-01 13:44:08 -04:00

82 lines
2.4 KiB
Text

use std::io;
use rand::{Rng,thread_rng};
extern crate rand;
const NUMBER_OF_DIGITS: usize = 4;
static DIGITS: [char; 9] = ['1', '2', '3', '4', '5', '6', '7', '8', '9'];
fn generate_digits() -> Vec<char> {
let mut temp_digits: Vec<_> = (&DIGITS[..]).into();
thread_rng().shuffle(&mut temp_digits);
return temp_digits.iter().take(NUMBER_OF_DIGITS).map(|&a| a).collect();
}
fn parse_guess_string(guess: &str) -> Result<Vec<char>, String> {
let chars: Vec<char> = (&guess).chars().collect();
if !chars.iter().all(|c| DIGITS.contains(c)) {
return Err("only digits, please".to_string());
}
if chars.len() != NUMBER_OF_DIGITS {
return Err(format!("you need to guess with {} digits", NUMBER_OF_DIGITS));
}
let mut uniques: Vec<char> = chars.clone();
uniques.dedup();
if uniques.len() != chars.len() {
return Err("no duplicates, please".to_string());
}
return Ok(chars);
}
fn calculate_score(given_digits: &[char], guessed_digits: &[char]) -> (usize, usize) {
let mut bulls = 0;
let mut cows = 0;
for i in 0..NUMBER_OF_DIGITS {
let pos: Option<usize> = guessed_digits.iter().position(|&a| -> bool {a == given_digits[i]});
match pos {
None => (),
Some(p) if p == i => bulls += 1,
Some(_) => cows += 1
}
}
return (bulls, cows);
}
fn main() {
let reader = io::stdin();
loop {
let given_digits = generate_digits();
println!("I have chosen my {} digits. Please guess what they are", NUMBER_OF_DIGITS);
loop {
let guess_string: String = {
let mut buf = String::new();
reader.read_line(&mut buf).unwrap();
buf.trim().into()
};
let digits_maybe = parse_guess_string(&guess_string);
match digits_maybe {
Err(msg) => {
println!("{}", msg);
continue;
},
Ok(guess_digits) => {
match calculate_score(&given_digits, &guess_digits) {
(NUMBER_OF_DIGITS, _) => {
println!("you win!");
break;
},
(bulls, cows) => println!("bulls: {}, cows: {}", bulls, cows)
}
}
}
}
}
}