feat: day 7

allow to only run specific days
This commit is contained in:
Lucy 2024-12-07 11:01:10 +01:00
parent 506fec4365
commit 8d74075bd9
4 changed files with 141 additions and 8 deletions

View file

@ -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

9
inputs/day07/example.txt Normal file
View file

@ -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

92
src/day07.rs Normal file
View file

@ -0,0 +1,92 @@
pub fn pt1(input: &str) -> usize {
input
.lines()
.map(|line| line.split_once(": ").unwrap())
.map(|(res, args)| {
(
res.parse::<usize>().unwrap(),
args.split(' ')
.flat_map(str::parse::<usize>)
.collect::<Vec<_>>(),
)
})
.filter(can_calibrate)
.map(|(val, _)| val)
.sum()
}
fn can_calibrate((res, args): &(usize, Vec<usize>)) -> 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<usize>)) -> 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::<usize>().unwrap(),
args.split(' ')
.flat_map(str::parse::<usize>)
.collect::<Vec<_>>(),
)
})
.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)
}
}

View file

@ -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<Fa, Fb, Ta, Tb>(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");
},
}
}