diff --git a/Cargo.toml b/Cargo.toml index 53e7b39..688601f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] +rand = "0.10.0" +rand_distr = "0.6.0" diff --git a/src/main.rs b/src/main.rs index e7a11a9..eb7cd9a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,101 @@ +use rand::RngExt; +use rand_distr::Binomial; +use std::env; +use std::io; + fn main() { - println!("Hello, world!"); + let args = env::args().skip(1).collect::>(); + let options = Options::from_args(&args); + guess(&options) +} + +struct Options { + min: u32, + max: u32, + use_normal: bool, +} + +impl Options { + fn parse(&mut self, args: &Vec) { + let mut args = args.iter(); + while let Some(arg) = args.next() { + match arg.as_str() { + "--normal" => self.use_normal = true, + "--max" | "-m" => { + let max_value = args + .next() + .expect("Number proceeding --max should be a number"); + self.max = max_value + .trim() + .parse() + .expect("Number proceeding --max should be a number"); + } + "--min" => { + let min_value = args + .next() + .expect("Number proceeding --min should be a number"); + self.min = min_value + .trim() + .parse() + .expect("Number proceeding --min should be a number"); + } + _ => panic!("Unrecognized argument {:?}", arg), + } + } + if self.max < self.min { + panic!("min > max, wtf are you even talking about?"); + } + } + + fn from_args(args: &Vec) -> Options { + let mut opts = Options::new(); + opts.parse(args); + opts + } + + fn new() -> Options { + Options { + use_normal: false, + min: 0, + max: 10, + } + } +} + +fn random_uniform_range(min: u32, max: u32) -> u32 { + let diff = max - min; + (rand::random::() % diff) + min +} + +fn random_binomial_range(min: u32, max: u32) -> u32 { + let diff = max - min; + let bin = Binomial::new(diff as u64, 0.5).expect("Could not make range"); + rand::rng().sample(bin) as u32 + min +} + +fn guess(opts: &Options) { + let to_guess: u32 = match opts.use_normal { + true => random_binomial_range(opts.min, opts.max), + false => random_uniform_range(opts.min, opts.max), + }; + + let mut input_string = String::new(); + println!( + "Enter a number in the range {}<=guess<{}", + opts.min, opts.max + ); + io::stdin() + .read_line(&mut input_string) + .expect("Could not read string"); + + let input_number = input_string + .trim() + .parse::() + .expect("Could not parse input"); + + if input_number == to_guess { + println!("You got it right!"); + } else { + println!("The correct number was {}!", to_guess); + } }