Add Rust port of 05_Bagels

This commit is contained in:
Till Klister
2022-03-12 01:58:09 +01:00
parent 79c42ed907
commit 3b1a1c2f18
3 changed files with 143 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
[package]
name = "rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rand = "0.8.5"

3
05_Bagels/rust/README.md Normal file
View File

@@ -0,0 +1,3 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Rust](https://www.rust-lang.org/) by Till Klister [tikste@github](https://github.com/tikste).

131
05_Bagels/rust/src/main.rs Normal file
View File

@@ -0,0 +1,131 @@
use std::io;
use std::io::{stdin, stdout, Write};
use rand::prelude::SliceRandom;
type Digits = [u8; 3];
fn main() -> io::Result<()> {
print_header();
if !read_lowercase_input()?.starts_with('n') {
print_rules();
}
let mut win_count = 0;
loop {
let solution = generate_random_digits();
println!("\nO.K. I have a number in mind.");
if guess(solution)? {
win_count += 1;
println!("You got it!!!");
} else {
println!(
"\nOh well\nThat's twenty guesses: My number was {}{}{}",
solution[0], solution[1], solution[2]
);
}
println!("\nPlay again (yes or no)?");
if read_lowercase_input()? != "yes" {
println!();
if win_count > 0 {
println!("A {win_count} point bagels buff!!");
}
println!("Hope you had fun. Bye.");
return Ok(());
}
}
}
fn print_header() {
println!(" Bagels");
println!("Creative-Computing Morristown, New Jersey");
println!();
println!("Would you like the rules (yes or no)?");
}
fn print_rules() {
println!();
println!("I am thinking of a three-digit number. Try to guess");
println!("my number and I will give you clues as follows:");
println!(" Pico - one digit correct but in the wrong position");
println!(" Fermi - one digit correct and in the right position");
println!(" Bagles - no digits correct");
}
fn read_lowercase_input() -> io::Result<String> {
let mut input = String::new();
stdin().read_line(&mut input)?;
Ok(input.trim().to_lowercase())
}
fn generate_random_digits() -> Digits {
let range = 0..10;
let mut numbers = range.into_iter().collect::<Vec<u8>>();
numbers.shuffle(&mut rand::thread_rng());
let mut digits = Digits::default();
let len = digits.len();
digits.copy_from_slice(&numbers[..len]);
digits
}
fn guess(solution: Digits) -> io::Result<bool> {
for round in 1..21 {
let guess = read_valid_guess(round)?;
if guess == solution {
return Ok(true);
} else {
let mut pico = 0;
let mut fermi = 0;
for i in 0..guess.len() {
if guess[i] == solution[i] {
fermi += 1;
} else if solution.contains(&guess[i]) {
pico += 1;
}
}
let mut status = String::new();
if pico == 0 && fermi == 0 {
status += "Bagels";
} else {
for _ in 0..pico {
status += "Pico ";
}
for _ in 0..fermi {
status += "Fermi ";
}
};
println!("{}", status.trim_end());
}
}
Ok(false)
}
fn read_valid_guess(round: u8) -> io::Result<Digits> {
let mut guess = Digits::default();
loop {
let space = " ".repeat(if round < 10 { 5 } else { 4 });
print!("Guess #{round}{space}? ");
stdout().flush()?;
let input = read_lowercase_input()?;
if input.len() == guess.len() {
let mut i = 0;
for c in input.chars() {
if let Ok(digit) = c.to_string().parse::<u8>() {
if guess[..i].contains(&digit) {
println!("\nOh, I forgot to tell you that the number I have in mind\nhas no two digits the same.");
break;
}
guess[i] = digit;
i += 1;
if i == guess.len() {
return Ok(guess);
}
} else {
println!("What?");
break;
}
}
} else {
println!("Try guessing a three-digit number.");
}
}
}