diff --git a/Cargo.lock b/Cargo.lock index bb03321..387ebd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,9 +32,9 @@ version = "0.0.0" dependencies = [ "anyhow", "cached", - "derive_more", "glam", "itertools", + "rayon", ] [[package]] @@ -82,6 +82,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "darling" version = "0.20.11" @@ -117,27 +142,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" @@ -229,12 +233,23 @@ dependencies = [ ] [[package]] -name = "rustc_version" -version = "0.4.1" +name = "rayon" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ - "semver", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", ] [[package]] @@ -243,12 +258,6 @@ 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 63cbbb3..df45d61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,9 @@ 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" +rayon = "1.11.0" [profile.release] debug = true diff --git a/src/bin/09.rs b/src/bin/09.rs index 4de6d4c..6c20878 100644 --- a/src/bin/09.rs +++ b/src/bin/09.rs @@ -1,8 +1,7 @@ use aoc::*; -use derive_more::Deref; use glam::I64Vec2; use itertools::Itertools; -use std::cmp::Reverse; +use rayon::prelude::*; use std::collections::HashMap; const INPUT: &str = include_str!("../../input/09"); @@ -45,19 +44,19 @@ fn part2(input: &str) -> u64 { .iter() .copied() .tuple_combinations() + .par_bridge() .map(Rect::from) - .sorted_by_key(|r| { - let area = r.uncompress(&uncompress).area(); - Reverse(area) - }) - .find(|&r| polygon.contains_rect(r)) + .filter(|&r| polygon.contains_rect(r)) + .map(|r| r.uncompress(&uncompress).area()) + .max() .unwrap() - .uncompress(&uncompress) - .area() } struct Polygon { points: Vec, + /// Contains vertical lines sorted by their x value in ascending order. + /// This is important for contains_point, as that assumes the lines are in this order. + /// This dramatically speeds up the raycast in contains_point, as the ray is cast in positive x direction. cached_vertical_lines: Vec, } @@ -72,7 +71,7 @@ impl Polygon { fn parse(input: &str) -> Self { let mut polygon = Self { points: input.lines().map(parse_line).collect(), - cached_vertical_lines: vec![], + cached_vertical_lines: Default::default(), }; polygon.cache_vertical_lines(); polygon @@ -127,19 +126,20 @@ impl Polygon { let xs = self .cached_vertical_lines .iter() + .take_while(|line| line.0.x < p.x) .filter(|l| { let ymin = l.0.y.min(l.1.y); let ymax = l.0.y.max(l.1.y); ymin <= p.y && p.y <= ymax }) - .flat_map(|l| [l.0.x]) - .filter(|&x| x < p.x) + .map(|l| l.0.x) .chain([p.x]) .sorted(); - let line = |p| { + let line_with = |p: I64Vec2| { self.cached_vertical_lines .iter() + .take_while(|line| line.0.x <= p.x) .find(|line| line.contains(p)) .copied() }; @@ -149,7 +149,7 @@ impl Polygon { for x in xs { let check = I64Vec2::new(x, p.y); - if let Some(line) = line(check) { + if let Some(line) = line_with(check) { winding = line.winding(); on_line = true; } else { @@ -160,19 +160,17 @@ impl Polygon { winding < 0 || on_line } - fn vertical_lines(&self) -> Vec { - self.points + fn cache_vertical_lines(&mut self) { + self.cached_vertical_lines = self + .points .iter() .chain(self.points.first()) // close the loop .copied() .tuple_windows() .map(|(a, b)| Line(a, b)) .filter(|l| l.is_vertical()) - .collect() - } - - fn cache_vertical_lines(&mut self) { - self.cached_vertical_lines = self.vertical_lines(); + .sorted_by_key(|line| line.0.x) + .collect(); } }