From 70df5770fb0b922a5cd62c19e89b8cf49976b784 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Fri, 3 May 2024 13:49:33 -0500 Subject: [PATCH] Parse input from stdin, improve output --- Cargo.lock | 59 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ src/main.rs | 80 ++++++++++++++++++++++++++++++++--------------------- 3 files changed, 109 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 76ef877..70efa79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,49 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anyhow" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + [[package]] name = "getrandom" version = "0.2.14" @@ -29,7 +66,9 @@ checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" name = "lotto" version = "0.1.0" dependencies = [ + "anyhow", "rand", + "rayon", ] [[package]] @@ -68,6 +107,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index a07e463..677712a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0.82" rand = "0.8.5" +rayon = "1.10.0" diff --git a/src/main.rs b/src/main.rs index 62b00a3..aafbbe4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,34 +1,37 @@ -use rand::Rng; -use std::time::Instant; +use anyhow::anyhow; +use std::io::BufRead; +use std::{ + io::{stdin, BufReader}, + time::Instant, +}; type Ticket = [u8; 5]; const NUM_ENTRIES: usize = 10_000_000; -// println!("char: {}", rand::random::()); +fn ticket_from_str(s: &str) -> Result { + let mut nums = s.split(" ").take(5).map(|s| s.parse::()).into_iter(); -fn gen_num() -> u8 { - rand::thread_rng().gen_range(0..90) -} + let num1 = nums.next(); + let num2 = nums.next(); + let num3 = nums.next(); + let num4 = nums.next(); + let num5 = nums.next(); + if num1.is_none() || num2.is_none() || num3.is_none() || num4.is_none() || num5.is_none() { + return Err(anyhow!("invalid lotto number")); + } + let r = [ + num1.unwrap()?, + num2.unwrap()?, + num3.unwrap()?, + num4.unwrap()?, + num5.unwrap()?, + ]; -fn gen_ticket() -> Ticket { - let num1 = gen_num(); - let mut num2: u8 = gen_num(); - while num2 == num1 { - num2 = gen_num() + if r[0] > 90 || r[1] > 90 || r[2] > 90 || r[3] > 90 || r[4] > 90 { + return Err(anyhow!("lotto number too high")); } - let mut num3: u8 = gen_num(); - while num3 == num1 || num3 == num2 { - num3 = gen_num() - } - let mut num4: u8 = gen_num(); - while num4 == num1 || num4 == num2 || num4 == num3 { - num4 = gen_num() - } - let mut num5: u8 = gen_num(); - while num5 == num1 || num5 == num2 || num5 == num3 || num5 == num4 { - num5 = gen_num() - } - [num1, num2, num3, num4, num5] + + Ok(r) } fn num_matches(t1: Ticket, t2: Ticket) -> usize { @@ -43,17 +46,27 @@ fn num_matches(t1: Ticket, t2: Ticket) -> usize { result } -fn main() { - println!("Generating entries"); - let mut entries: Vec = Vec::with_capacity(NUM_ENTRIES); - for _ in 0..NUM_ENTRIES { - entries.push(gen_ticket()); +fn main() -> Result<(), anyhow::Error> { + println!("Parsing entries"); + + let reader = BufReader::new(stdin()); + let mut entries = Vec::with_capacity(NUM_ENTRIES); + + for line in reader.lines() { + match line { + Ok(l) => match ticket_from_str(&l) { + Ok(n) => entries.push(n), + Err(_) => {} // noop + }, + Err(_) => break, + } } - let winning = gen_ticket(); + println!("{} entries parsed from stdin", entries.len()); + + let winning = [68, 81, 40, 34, 85]; let start = Instant::now(); - - println!("Counting winners..."); + println!("Counting winners... (timer started)"); let mut winners: [usize; 6] = [0, 0, 0, 0, 0, 0]; for n in entries { @@ -61,6 +74,7 @@ fn main() { winners[num_winning] += 1 } + println!("Done counting winners (timer stopped)"); let duration = start.elapsed(); println!( @@ -68,4 +82,6 @@ fn main() { winners, duration.subsec_millis() ); + + Ok(()) }