From 8d74075bd9e553a4f1fc570395d64cb7ae2c1860 Mon Sep 17 00:00:00 2001 From: Lucy Date: Sat, 7 Dec 2024 11:01:10 +0100 Subject: [PATCH] feat: day 7 allow to only run specific days --- Cargo.toml | 11 +++++ inputs/day07/example.txt | 9 ++++ src/day07.rs | 92 ++++++++++++++++++++++++++++++++++++++++ src/main.rs | 37 ++++++++++++---- 4 files changed, 141 insertions(+), 8 deletions(-) create mode 100644 inputs/day07/example.txt create mode 100644 src/day07.rs diff --git a/Cargo.toml b/Cargo.toml index 60c68c2..ee4bc43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,17 @@ name = "aoc2024" version = "0.1.0" edition = "2021" +[features] +full = ["day1", "day2", "day3", "day4", "day5", "day6", "day7"] +default = ["full"] +day1 = [] +day2 = [] +day3 = [] +day4 = [] +day5 = [] +day6 = [] +day7 = [] + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/inputs/day07/example.txt b/inputs/day07/example.txt new file mode 100644 index 0000000..fc6e099 --- /dev/null +++ b/inputs/day07/example.txt @@ -0,0 +1,9 @@ +190: 10 19 +3267: 81 40 27 +83: 17 5 +156: 15 6 +7290: 6 8 6 15 +161011: 16 10 13 +192: 17 8 14 +21037: 9 7 18 13 +292: 11 6 16 20 diff --git a/src/day07.rs b/src/day07.rs new file mode 100644 index 0000000..3917f5c --- /dev/null +++ b/src/day07.rs @@ -0,0 +1,92 @@ +pub fn pt1(input: &str) -> usize { + input + .lines() + .map(|line| line.split_once(": ").unwrap()) + .map(|(res, args)| { + ( + res.parse::().unwrap(), + args.split(' ') + .flat_map(str::parse::) + .collect::>(), + ) + }) + .filter(can_calibrate) + .map(|(val, _)| val) + .sum() +} +fn can_calibrate((res, args): &(usize, Vec)) -> bool { + (0..(2usize << args.len())).any(|mut i| { + let mut arg_clone = args.iter(); + let mut current_res = *arg_clone.next().unwrap(); + for arg in arg_clone { + let op = i & 1; + if op == 1 { + current_res += arg; + } else { + current_res *= arg; + } + i >>= 1; + } + current_res == *res + }) +} + +fn can_calibrate_concat((res, args): &(usize, Vec)) -> bool { + (0..(3usize.pow(u32::try_from(args.len()).unwrap()))).any(|mut i| { + let mut arg_clone = args.iter(); + let mut current_res = *arg_clone.next().unwrap(); + for arg in arg_clone { + let op = i % 3; + match op { + 0 => current_res += arg, + 1 => current_res *= arg, + 2 => { + current_res *= 10usize.pow(u32::try_from(arg.to_string().len()).unwrap()); + current_res += arg; + } + _ => unreachable!(), + } + i /= 3; + if current_res > *res { + return false; + } + } + current_res == *res + }) +} +pub fn pt2(input: &str) -> usize { + input + .lines() + .map(|line| line.split_once(": ").unwrap()) + .map(|(res, args)| { + ( + res.parse::().unwrap(), + args.split(' ') + .flat_map(str::parse::) + .collect::>(), + ) + }) + .filter(can_calibrate_concat) + .map(|(val, _)| val) + .sum() +} + +#[cfg(test)] +mod tests { + use super::{pt1, pt2}; + use std::fs::read_to_string; + + #[test] + pub fn test_pt1() { + let input = + read_to_string("./inputs/day07/example.txt").expect("Missing example.txt for day07"); + assert_eq!(pt1(&input), 3749) + } + #[test] + pub fn test_pt2() { + let input = + read_to_string("./inputs/day07/example.txt").expect("Missing example.txt for day07"); + + assert_eq!(pt2(&input), 11387) + } +} diff --git a/src/main.rs b/src/main.rs index b1f4ea3..e26d0d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,37 @@ use std::{fmt::Display, fs::read_to_string, time::Instant}; +#[cfg(feature = "day1")] mod day01; +#[cfg(feature = "day2")] mod day02; +#[cfg(feature = "day3")] mod day03; +#[cfg(feature = "day4")] mod day04; +#[cfg(feature = "day5")] mod day05; +#[cfg(feature = "day6")] mod day06; +#[cfg(feature = "day7")] +mod day07; fn main() { color_eyre::install().unwrap(); tracing_subscriber::fmt().init(); + #[cfg(feature = "day1")] solve_day(1, day01::pt1, day01::pt2); + #[cfg(feature = "day2")] solve_day(2, day02::pt1, day02::pt2); + #[cfg(feature = "day3")] solve_day(3, day03::pt1, day03::pt2); + #[cfg(feature = "day4")] solve_day(4, day04::pt1, day04::pt2); + #[cfg(feature = "day5")] solve_day(5, day05::pt1, day05::pt2); + #[cfg(feature = "day6")] solve_day(6, day06::pt1, day06::pt2); + #[cfg(feature = "day7")] + solve_day(7, day07::pt1, day07::pt2); } fn solve_day(day: u8, part_a: Fa, part_b: Fb) @@ -25,12 +41,17 @@ where Fb: Fn(&str) -> Tb, Tb: Display, { - let input = read_to_string(format!("./inputs/day{day:02}/input.txt")) - .unwrap_or_else(|_| panic!("Missing input.txt for day{day:02}")); - let start = Instant::now(); - let result_a = part_a(&input); - tracing::info!("[{day:02}] Part A: {result_a} \tin {:?}", start.elapsed()); - let start = Instant::now(); - let result_b = part_b(&input); - tracing::info!("[{day:02}] Part B: {result_b} \tin {:?}", start.elapsed()); + match read_to_string(format!("./inputs/day{day:02}/input.txt")) { + Ok(input) => { + let start = Instant::now(); + let result_a = part_a(&input); + tracing::info!("[{day:02}] Part A: {result_a} \tin {:?}", start.elapsed()); + let start = Instant::now(); + let result_b = part_b(&input); + tracing::info!("[{day:02}] Part B: {result_b} \tin {:?}", start.elapsed()); + } + Err(_) => { + tracing::warn!("could not open ./inputs/day{day:02}/input.txt"); + }, + } }