From ba5e9e78d6a10b037f748f9ff60d6d0acf166920 Mon Sep 17 00:00:00 2001 From: mirsella Date: Sun, 8 Dec 2024 07:30:46 +0100 Subject: [PATCH] add day8 --- 2024/day8/.gitignore | 19 ++++++++ 2024/day8/Cargo.toml | 15 +++++++ 2024/day8/src/main.rs | 100 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 2024/day8/.gitignore create mode 100644 2024/day8/Cargo.toml create mode 100644 2024/day8/src/main.rs diff --git a/2024/day8/.gitignore b/2024/day8/.gitignore new file mode 100644 index 0000000..e983cca --- /dev/null +++ b/2024/day8/.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/day8/Cargo.toml b/2024/day8/Cargo.toml new file mode 100644 index 0000000..a80fefd --- /dev/null +++ b/2024/day8/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "day8" +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 } +glam = { version = "0.29.2", features = ["debug-glam-assert"] } diff --git a/2024/day8/src/main.rs b/2024/day8/src/main.rs new file mode 100644 index 0000000..aa6a90f --- /dev/null +++ b/2024/day8/src/main.rs @@ -0,0 +1,100 @@ +use glam::Vec2; +use pathfinding::matrix::Matrix; +use std::collections::HashSet; + +fn part1(input: &str) -> usize { + let m = Matrix::from_rows(input.lines().map(str::chars)).unwrap(); + let mut set = HashSet::new(); + for (apos, c) in m.items() { + if *c == '.' { + continue; + } + for (bpos, cb) in m.items() { + if c != cb || apos == bpos { + continue; + } + let avec = Vec2::new(apos.1 as f32, apos.0 as f32); + let bvec = Vec2::new(bpos.1 as f32, bpos.0 as f32); + let anewvec = avec.lerp(bvec, 2.); + let bnewvec = bvec.lerp(avec, 2.); + let anew = (anewvec.y as usize, anewvec.x as usize); + let bnew = (bnewvec.y as usize, bnewvec.x as usize); + if anewvec.x >= 0. && anewvec.y >= 0. && m.within_bounds(anew) { + set.insert(anew); + } + if bnewvec.x >= 0. && bnewvec.y >= 0. && m.within_bounds(bnew) { + set.insert(bnew); + } + } + } + set.len() +} +fn part2(input: &str) -> usize { + let m = Matrix::from_rows(input.lines().map(str::chars)).unwrap(); + let mut set = HashSet::new(); + for (apos, c) in m.items() { + if *c == '.' { + continue; + } + for (bpos, cb) in m.items().skip(apos.0 + apos.1) { + if c != cb || apos == bpos { + continue; + } + let avec = Vec2::new(apos.1 as f32, apos.0 as f32); + let bvec = Vec2::new(bpos.1 as f32, bpos.0 as f32); + let mut factor = 1.; + loop { + let mut out = [false; 2]; + let anewvec = avec + (bvec - avec) * factor; + let bnewvec = bvec + (avec - bvec) * factor; + let anew = (anewvec.y as usize, anewvec.x as usize); + let bnew = (bnewvec.y as usize, bnewvec.x as usize); + if anewvec.x >= 0. && anewvec.y >= 0. && m.within_bounds(anew) { + set.insert(anew); + } else { + out[0] = true; + } + if bnewvec.x >= 0. && bnewvec.y >= 0. && m.within_bounds(bnew) { + set.insert(bnew); + } else { + out[1] = true; + } + if out[0] && out[1] { + break; + } + factor += 1.; + } + } + } + set.len() +} + +fn main() { + let input = include_str!("../input.txt"); + println!("Part 1: {}", part1(input)); + println!("Part 2: {}", part2(input)); +} + +#[cfg(test)] +mod tests { + const INPUT: &str = "............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............"; + #[test] + fn part1() { + assert_eq!(super::part1(INPUT), 14); + } + #[test] + fn part2() { + assert_eq!(super::part2(INPUT), 34); + } +}