diff --git a/Cargo.lock b/Cargo.lock index bb03321..c032e7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,7 +32,6 @@ version = "0.0.0" dependencies = [ "anyhow", "cached", - "derive_more", "glam", "itertools", ] @@ -117,27 +116,6 @@ dependencies = [ "syn", ] -[[package]] -name = "derive_more" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "syn", -] - [[package]] name = "either" version = "1.13.0" @@ -228,27 +206,12 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "semver" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" - [[package]] name = "strsim" version = "0.11.1" diff --git a/Cargo.toml b/Cargo.toml index 234fed2..3aa0d95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,5 @@ edition = "2021" [dependencies] anyhow = "1.0.100" cached = "0.56.0" -derive_more = { version = "2.1.0", features = ["deref"] } glam = "0.30.9" itertools = "0.14.0" diff --git a/src/bin/08.rs b/src/bin/08.rs index 14c24ad..37191c0 100644 --- a/src/bin/08.rs +++ b/src/bin/08.rs @@ -46,8 +46,8 @@ fn part2(input: &str) -> usize { } fn connect(mut circuits: Vec, (a, b): (JBox, JBox)) -> Vec { - let with_a = circuits.iter().position(|c| c.contains(&a)); - let with_b = circuits.iter().position(|c| c.contains(&b)); + let with_a = circuits.iter_mut().position(|c| c.contains(&a)); + let with_b = circuits.iter_mut().position(|c| c.contains(&b)); match (with_a, with_b) { (Some(with_a), Some(with_b)) => { // Merge into with_a. with_b will be empty, but whatever. @@ -71,7 +71,8 @@ fn pairs(boxes: &[JBox]) -> impl Iterator + use<'_> { boxes .iter() .copied() - .tuple_combinations() + .combinations(2) + .map(|v| (v[0], v[1])) .sorted_by_key(|&(a, b)| distance(a, b)) } diff --git a/src/bin/09.rs b/src/bin/09.rs deleted file mode 100644 index 83eafbf..0000000 --- a/src/bin/09.rs +++ /dev/null @@ -1,132 +0,0 @@ -use aoc::*; -use derive_more::Deref; -use glam::U64Vec2; -use itertools::Itertools; -use std::ops::Sub; - -const INPUT: &str = include_str!("../../input/09"); - -fn main() { - println!("Part 1: {}", part1(INPUT)); - println!("Part 2: {}", part2(INPUT)); -} - -#[test] -fn example() { - assert_example!(part1, "09-test", 50); - assert!(Line(U64Vec2::new(0, 10), U64Vec2::ZERO).contains(U64Vec2::new(0, 0))); - assert!(Line(U64Vec2::new(0, 10), U64Vec2::ZERO).contains(U64Vec2::new(0, 10))); - assert!(!Line(U64Vec2::new(0, 10), U64Vec2::ZERO).contains(U64Vec2::new(0, 11))); - assert!(!Line(U64Vec2::new(0, 10), U64Vec2::ZERO).contains(U64Vec2::new(1, 10))); - assert_example!(part2, "09-test", 24); -} - -fn part1(input: &str) -> u64 { - Polygon::parse(input) - .0 - .into_iter() - .tuple_combinations() - .map(Rect::from) - .map(Rect::area) - .max() - .unwrap() -} - -fn part2(input: &str) -> u64 { - let polygon = Polygon::parse(input); - polygon - .iter() - .copied() - .tuple_combinations() - .map(Rect::from) - .filter(|&r| polygon.contains_rect(r)) - .map(Rect::area) - .max() - .unwrap() -} - -#[derive(Deref)] -struct Polygon(Vec); - -impl Polygon { - fn parse(input: &str) -> Self { - Self(input.lines().map(parse_line).collect()) - } - - fn contains_rect(&self, r: Rect) -> bool { - r.all_points().into_iter().all(|p| self.contains_point(p)) - } - - /// Raycast from left to right and check intersections with lines. - fn contains_point(&self, p: U64Vec2) -> bool { - let lines = self.lines(); - let is_on_line = |p| lines.iter().any(|line| line.contains(p)); - - let mut inside = false; - let mut was_on_line = false; - - for x in 0..=p.x { - let check = U64Vec2::new(x, p.y); - let is_on_line = is_on_line(check); - let crossed = !is_on_line && was_on_line; - if crossed { - inside ^= true; - } - was_on_line = is_on_line; - } - - inside || was_on_line - } - - fn lines(&self) -> Vec { - self.iter() - .chain(self.first()) // close the loop - .copied() - .tuple_combinations() - .map(|(a, b)| Line(a, b)) - .collect() - } -} - -#[derive(Clone, Copy)] -struct Line(U64Vec2, U64Vec2); - -impl Line { - /// true if p on Line(a, b) - fn contains(&self, p: U64Vec2) -> bool { - let a = self.0.sub(p).length_squared(); - let b = self.1.sub(p).length_squared(); - let c = self.0.sub(self.1).length_squared(); - a + b == c - } -} - -#[derive(Copy, Clone)] -struct Rect(U64Vec2, U64Vec2); - -impl Rect { - fn area(self) -> u64 { - (self.0.x.abs_diff(self.1.x) + 1) * (self.0.y.abs_diff(self.1.y) + 1) - } - - fn from((a, b): (U64Vec2, U64Vec2)) -> Self { - Self(a, b) - } - - fn all_points(self) -> Vec { - let mut result = Vec::new(); - - for x in self.0.x.min(self.1.x)..=self.0.x.max(self.1.x) { - for y in self.0.y.min(self.1.y)..=self.0.y.max(self.1.y) { - result.push(U64Vec2::new(x, y)); - } - } - - result - } -} - -fn parse_line(line: &str) -> U64Vec2 { - let (x, y) = line.split_once(',').unwrap(); - U64Vec2::new(x.parse().unwrap(), y.parse().unwrap()) -}