From 161b3414000e787005aab415f4d4e46e763df5d0 Mon Sep 17 00:00:00 2001 From: Ty Date: Tue, 5 Dec 2023 00:03:50 -0700 Subject: [PATCH] Add login checks and example solving --- src/day5/mod.rs | 76 +++++++++++++++++++++++++------------------------ src/fetcher.rs | 11 +++++-- src/main.rs | 37 +++++++++++++----------- 3 files changed, 67 insertions(+), 57 deletions(-) diff --git a/src/day5/mod.rs b/src/day5/mod.rs index 72a0a1a..27d1f13 100644 --- a/src/day5/mod.rs +++ b/src/day5/mod.rs @@ -28,21 +28,18 @@ impl Day for Day5 { .map(|(name, list)| { ( name.split_once(' ').unwrap().0.split_once("-to-").unwrap(), - list.into_iter().map(|line| { - let nums = line.split_whitespace() - .map(|n| n.parse::().unwrap()) - .collect::>(); - (nums[0], nums[1], nums[2]) - }).collect::>(), + list.into_iter() + .map(|line| { + let nums = line + .split_whitespace() + .map(|n| n.parse::().unwrap()) + .collect::>(); + (nums[0], nums[1], nums[2]) + }) + .collect::>(), ) }) - .map(|((from, to), mappings)| ( - from, - ( - to, - mappings - ) - )) + .map(|((from, to), mappings)| (from, (to, mappings))) .collect::)>>(); let mut locations = Vec::::new(); @@ -90,29 +87,24 @@ impl Day for Day5 { .split_whitespace() .map(|s| s.parse::().unwrap()) .collect::>(); - let seeds = seeds - .as_slice() - .chunks(2); + let seeds = seeds.as_slice().chunks(2); let groups = groups .map(|(name, list)| { ( name.split_once(' ').unwrap().0.split_once("-to-").unwrap(), - list.into_iter().map(|line| { - let nums = line.split_whitespace() - .map(|n| n.parse::().unwrap()) - .collect::>(); - (nums[0], nums[1], nums[2]) - }).collect::>(), + list.into_iter() + .map(|line| { + let nums = line + .split_whitespace() + .map(|n| n.parse::().unwrap()) + .collect::>(); + (nums[0], nums[1], nums[2]) + }) + .collect::>(), ) }) - .map(|((from, to), mappings)| ( - from, - ( - to, - mappings - ) - )) + .map(|((from, to), mappings)| (from, (to, mappings))) .collect::)>>(); let mut location = 100000000usize; @@ -122,13 +114,20 @@ impl Day for Day5 { let (initial, range) = (chunk[0], chunk[1]); for (j, seed) in (initial..(initial + range)).enumerate() { if j % 1000 == 0 { - println!("Chunk {}/{}, Seed {}/{} ({:.2}%)", i, seedslen, j, range, j as f64 / range as f64 * 100.0); + println!( + "Chunk {}/{}, Seed {}/{} ({:.2}%)", + i, + seedslen, + j, + range, + j as f64 / range as f64 * 100.0 + ); } let (mut category, mut value) = ("seed", seed); while category != "location" { let (new_category, mappings) = groups.get(category).unwrap(); category = new_category; - + for (destination_start, source_start, length) in mappings { if (source_start..&(source_start + length)).contains(&&value) { let delta = *source_start as isize - *destination_start as isize; @@ -137,8 +136,10 @@ impl Day for Day5 { } } } - - if location > value { location = value } + + if location > value { + location = value + } } } @@ -146,7 +147,6 @@ impl Day for Day5 { } } - #[cfg(test)] mod tests { use crate::{day5::Day5, utils::Day}; @@ -186,7 +186,8 @@ temperature-to-humidity map: humidity-to-location map: 60 56 37 -56 93 4"#.to_string(), +56 93 4"# + .to_string(), } .solve(1)); } @@ -226,8 +227,9 @@ temperature-to-humidity map: humidity-to-location map: 60 56 37 -56 93 4"#.to_string(), +56 93 4"# + .to_string(), } .solve(2)); } -} \ No newline at end of file +} diff --git a/src/fetcher.rs b/src/fetcher.rs index e51f73a..329ac48 100644 --- a/src/fetcher.rs +++ b/src/fetcher.rs @@ -1,7 +1,7 @@ use scraper::{Html, Selector}; pub async fn fetch_input(auth: String, day: u8) -> String { - reqwest::Client::new() + let input = reqwest::Client::new() .get(format!("https://adventofcode.com/2023/day/{day}/input")) .header("Cookie", format!("session={auth}")) .send() @@ -11,7 +11,12 @@ pub async fn fetch_input(auth: String, day: u8) -> String { .await .expect("Unable to parse string from input response") .trim_end() - .to_owned() + .to_owned(); + if input != "Puzzle inputs differ by user. Please log in to get your puzzle input." { + input + } else { + panic!("Invalid auth") + } } pub async fn fetch_example(auth: String, day: u8, part: u8) -> (String, String) { @@ -44,7 +49,7 @@ pub async fn fetch_example(auth: String, day: u8, part: u8) -> (String, String) let solution = dom .select(&solution_selector) .last() - .unwrap() + .expect("Unable to find example solution for part, is auth correct?") .inner_html() .trim_end() .to_string(); diff --git a/src/main.rs b/src/main.rs index 6daa101..c0c5f0e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,9 @@ enum Subcommands { day: u8, /// The part to solve for part: u8, + /// If used, then the example input will be solved and checked rather than the real one + #[arg(short, long)] + example: bool, }, /// Runs solution N amount of times, averaging speed Benchmark { @@ -67,32 +70,28 @@ async fn main() { let client = reqwest::Client::new(); match cli.subcommand { - Subcommands::Solve { day, part } => { - let response = client - .get(format!("https://adventofcode.com/2023/day/{day}/input")) - .header("Cookie", format!("session={auth}", auth = cli.auth)) - .send() - .await - .unwrap() - .text() - .await - .unwrap() - .trim_end() - .to_owned(); + Subcommands::Solve { day, part, example } => { + let (input, solution) = match example { + false => (fetcher::fetch_input(cli.auth, day).await, None), + true => { + let example = fetcher::fetch_example(cli.auth, day, part).await; + (example.0, Some(example.1)) + } + }; let mut day: Box = match day { - 1 => Box::new(Day1 { input: response }), + 1 => Box::new(Day1 { input }), 2 => Box::new(Day2 { - input: response, + input, games: vec![], }), - 3 => Box::new(Day3 { input: response }), + 3 => Box::new(Day3 { input }), 4 => Box::new(Day4 { - input: response, + input, acc: 0usize, cards: HashMap::new(), }), - 5 => Box::new(Day5 { input: response }), + 5 => Box::new(Day5 { input }), _ => panic!("Invalid day #"), }; let start = std::time::Instant::now(); @@ -100,6 +99,10 @@ async fn main() { let end = std::time::Instant::now(); println!("Solution: {result}"); + if let Some(solution) = solution { + println!("Correct solution: {solution}") + } + let timing = (end - start).as_nanos(); let (timing, timing_units) = if timing >= 1000000000 { (timing as f64 / 1000000000.0, "s")