diff --git a/src/day8/mod.rs b/src/day8/mod.rs new file mode 100644 index 0000000..c389330 --- /dev/null +++ b/src/day8/mod.rs @@ -0,0 +1,63 @@ +use std::collections::HashMap; + +use crate::utils::Day; + +#[derive(Debug, Default)] +pub struct Day8 { + pub input: String, +} + +impl Day for Day8 { + fn part1(&mut self) -> String { + let (directions, map) = self.input.split_once("\n\n").unwrap(); + let map = map.lines().map(|line| line.split_once(" = (").unwrap()).map(|(from, to)| (from, to[..to.len()-1].split_once(", ").unwrap())).collect::>(); + + let mut current = "AAA"; + let mut i = 0; + + while current != "ZZZ" { + for direction in directions.chars() { + match direction { + 'L' => current = map[current].0, + 'R' => current = map[current].1, + _ => panic!() + } + + i += 1; + + if current == "ZZZ" { break } + } + } + + i.to_string() + } + + fn part2(&mut self) -> String { + let (directions, map) = self.input.split_once("\n\n").unwrap(); + let map = map.lines().map(|line| line.split_once(" = (").unwrap()).map(|(from, to)| (from, to[..to.len()-1].split_once(", ").unwrap())).collect::>(); + + let steps = map.keys().filter(|k| k.ends_with('A')).map(|current| { + let mut current = *current; + let mut i = 0usize; + let mut finished = false; + + while !finished { + for direction in directions.chars() { + match direction { + 'L' => current = map[current].0, + 'R' => current = map[current].1, + _ => panic!() + } + + if current.ends_with('Z') { finished = true; break; } + } + + i += 1; + } + + i + }).product::() * directions.len(); + + steps.to_string() + } +} diff --git a/src/main.rs b/src/main.rs index 816606c..5134f1b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,10 +4,10 @@ use std::{ time::{Duration, Instant}, }; -use clap::{Parser, Subcommand}; +use clap::{Parser, Subcommand, ValueEnum}; use crate::{ - day1::Day1, day2::Day2, day3::Day3, day4::Day4, day5::Day5, day6::Day6, day7::Day7, utils::Day, + day1::Day1, day2::Day2, day3::Day3, day4::Day4, day5::Day5, day6::Day6, day7::Day7, day8::Day8, utils::Day, }; pub mod day1; @@ -17,6 +17,7 @@ pub mod day4; pub mod day5; pub mod day6; pub mod day7; +pub mod day8; pub mod fetcher; pub mod utils; @@ -31,6 +32,14 @@ struct Cli { subcommand: Subcommands, } +#[derive(ValueEnum, Clone, PartialEq)] +pub enum InputType { + Normal, + Example, + Large, + Custom +} + #[derive(Subcommand)] enum Subcommands { /// Solves the specified part for the specified day, after fetching the input @@ -39,12 +48,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, group = "inputs")] - example: bool, - /// If used, then the large input will be solved and checked rather than the real one - #[arg(short, long, group = "inputs")] - large: bool, + /// Allows you to control the type of input used + #[arg(short, long)] + input: InputType, }, /// Runs solution N amount of times, averaging speed Benchmark { @@ -83,15 +89,13 @@ async fn main() { Subcommands::Solve { day, part, - example, - large, + input: input_type, } => { - let (input, solution) = match example { - false => match large { - false => (fetcher::fetch_input(cli.auth, day).await, None), - true => fetcher::fetch_large(day, part).await, - }, - true => fetcher::fetch_example(cli.auth, day, part).await + let (input, solution) = match input_type { + InputType::Normal => (fetcher::fetch_input(cli.auth, day).await, None), + InputType::Example => fetcher::fetch_example(cli.auth, day, part).await, + InputType::Large => fetcher::fetch_large(day, part).await, + InputType::Custom => (std::fs::read_to_string({ let mut p = std::env::current_dir().unwrap(); p.push("input.txt"); p }).unwrap(), None), }; let mut day: Box = match day { @@ -112,10 +116,11 @@ async fn main() { input, hands: vec![], }), + 8 => Box::new(Day8 { input }), _ => panic!("Invalid day #"), }; let start = std::time::Instant::now(); - let result = day.solve(part, large); + let result = day.solve(part, input_type == InputType::Large); let end = std::time::Instant::now(); println!("Solution: {result}"); @@ -168,6 +173,7 @@ async fn main() { input, hands: vec![], }), + 8 => Box::new(Day8 { input }), _ => panic!("Invalid day #"), }; let mut timings = Vec::::new();