From 522735185978aad6746cab2d44368c9ccb4adc21 Mon Sep 17 00:00:00 2001 From: mirsella Date: Sat, 14 Dec 2024 07:24:00 +0100 Subject: [PATCH] add day14 --- 2024/day14/.gitignore | 19 +++++++ 2024/day14/Cargo.toml | 16 ++++++ 2024/day14/src/main.rs | 119 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 2024/day14/.gitignore create mode 100644 2024/day14/Cargo.toml create mode 100644 2024/day14/src/main.rs diff --git a/2024/day14/.gitignore b/2024/day14/.gitignore new file mode 100644 index 0000000..e983cca --- /dev/null +++ b/2024/day14/.gitignore @@ -0,0 +1,19 @@ +input.txt +flamegraph.svg +perf.data* +### Rust +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + diff --git a/2024/day14/Cargo.toml b/2024/day14/Cargo.toml new file mode 100644 index 0000000..7e13999 --- /dev/null +++ b/2024/day14/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "day14" +authors = ["mirsella "] +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +regex = { workspace = true } +itertools = { workspace = true } +pathfinding = { workspace = true } +rayon = { workspace = true } +indexmap = { workspace = true } +hashbrown = { workspace = true } +fix_fn = { workspace = true } diff --git a/2024/day14/src/main.rs b/2024/day14/src/main.rs new file mode 100644 index 0000000..c6ef80e --- /dev/null +++ b/2024/day14/src/main.rs @@ -0,0 +1,119 @@ +use itertools::Itertools; + +fn part1(input: &str, wide: usize, high: usize) -> usize { + let wide = wide as i16; + let high = high as i16; + input + .lines() + .map(|l| { + let (mut x, mut y, vx, vy) = l + .split(['p', '=', ',', ' ', 'v']) + .filter(|s| !s.is_empty()) + .map(|s| s.parse::().unwrap()) + .collect_tuple() + .unwrap(); + (0..100).for_each(|_| { + x = (x + vx).rem_euclid(wide); + y = (y + vy).rem_euclid(high); + }); + let mut quadran = 0; + if x > wide / 2 { + quadran += 1; + } + if y > high / 2 { + quadran += 2; + } + if x == wide / 2 || y == high / 2 { + quadran += 4; + } + quadran + }) + .fold([0usize; 4], |mut acc, id| { + if id < 4 { + acc[id] += 1; + } + acc + }) + .into_iter() + .product() +} + +fn part2(input: &str, wide: usize, high: usize) -> usize { + let wide = wide as i16; + let high = high as i16; + let mut robots: Vec<(i16, i16, i16, i16)> = { + input + .lines() + .map(|l| { + l.split(['p', '=', ',', ' ', 'v']) + .filter(|s| !s.is_empty()) + .map(|s| s.parse::().unwrap()) + .collect_tuple() + .unwrap() + }) + .collect() + }; + let mut min_safety_factor = None; + for sec in 1..wide * high { + let safety_factor = robots + .iter_mut() + .map(|(x, y, vx, vy)| { + *x = (*x + *vx).rem_euclid(wide); + *y = (*y + *vy).rem_euclid(high); + + let mut quadran = 0; + if *x > wide / 2 { + quadran += 1; + } + if *y > high / 2 { + quadran += 2; + } + if *x == wide / 2 || *y == high / 2 { + quadran += 4; + } + quadran + }) + .fold([0usize; 4], |mut acc, id| { + if id < 4 { + acc[id] += 1; + } + acc + }) + .into_iter() + .product::(); + if let Some((_, mfactor)) = min_safety_factor { + if safety_factor < mfactor { + min_safety_factor = Some((sec, safety_factor)); + } + } else { + min_safety_factor = Some((sec, safety_factor)); + }; + } + min_safety_factor.unwrap().0 as usize +} + +fn main() { + let input = include_str!("../input.txt"); + println!("Part 1: {}", part1(input, 101, 103)); + println!("Part 2: {}", part2(input, 101, 103)); +} + +#[cfg(test)] +mod tests { + const INPUT: &str = "p=0,4 v=3,-3 +p=6,3 v=-1,-3 +p=10,3 v=-1,2 +p=2,0 v=2,-1 +p=0,0 v=1,3 +p=3,0 v=-2,-2 +p=7,6 v=-1,-3 +p=3,0 v=-1,-2 +p=9,3 v=2,3 +p=7,3 v=-1,2 +p=2,4 v=2,-3 +p=9,5 v=-3,-3"; + #[test] + fn part1() { + assert_eq!(super::part1(INPUT, 11, 7), 12); + } +}