From 530417e81668398187ce165df94bf48ea723bbbb Mon Sep 17 00:00:00 2001 From: Anthony Oteri Date: Tue, 12 Dec 2023 08:06:22 -0500 Subject: [PATCH] Day 11 - Part 2 Signed-off-by: Anthony Oteri --- day-11/Cargo.toml | 1 + day-11/benches/benchmark.rs | 4 +- day-11/src/part2.rs | 83 ++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/day-11/Cargo.toml b/day-11/Cargo.toml index 5b26fdf..28df548 100644 --- a/day-11/Cargo.toml +++ b/day-11/Cargo.toml @@ -13,6 +13,7 @@ tracing-subscriber = { workspace = true } miette = { workspace = true } thiserror = { workspace = true } dhat = { workspace = true } +rayon = { workspace = true } [dev-dependencies] divan = { workspace = true } diff --git a/day-11/benches/benchmark.rs b/day-11/benches/benchmark.rs index 7f60052..fce7637 100644 --- a/day-11/benches/benchmark.rs +++ b/day-11/benches/benchmark.rs @@ -6,10 +6,10 @@ fn main() { #[divan::bench] fn part1() { - part1::process(divan::black_box("../input.txt")).unwrap(); + part1::process(divan::black_box(include_str!("../input.txt"))).unwrap(); } #[divan::bench] fn part2() { - part2::process(divan::black_box("../input.txt")).unwrap(); + part2::process(divan::black_box(include_str!("../input.txt"))).unwrap(); } diff --git a/day-11/src/part2.rs b/day-11/src/part2.rs index 1ff3976..975bce2 100644 --- a/day-11/src/part2.rs +++ b/day-11/src/part2.rs @@ -1,8 +1,87 @@ +use std::collections::BTreeSet; + +use itertools::Itertools; + use crate::error::AocError; +use rayon::prelude::*; + +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] +struct Point { + x: usize, + y: usize, +} + +fn parse(input: &str) -> BTreeSet { + input + .lines() + .enumerate() + .flat_map(|(y, line)| { + line.chars().enumerate().filter_map(move |(x, c)| match c { + '#' => Some(Point { x, y }), + '.' => None, + _ => panic!("Unknown tile type"), + }) + }) + .collect::>() +} #[tracing::instrument] pub fn process(input: &str) -> miette::Result { - Ok(0) + let map = parse(input); + + let mut empty_rows = Vec::new(); + let mut empty_cols = Vec::new(); + + for n in 0..map.len() { + let empty_row: bool = !map.iter().any(|k| k.y == n); + let empty_col: bool = !map.iter().any(|k| k.x == n); + if empty_row { + empty_rows.push(n); + } + if empty_col { + empty_cols.push(n); + } + } + + let locations = map + .iter() + .map(|m| { + let dx = empty_cols.iter().filter(|&c| c < &m.x).count(); + let dy = empty_rows.iter().filter(|&r| r < &m.y).count(); + + Point { + x: m.x - dx + 1_000_000 * dx, + y: m.y - dy + 1_000_000 * dy, + } + }) + .collect::>(); + + let pairs: BTreeSet> = locations + .iter() + .cartesian_product(locations.iter()) + .filter(|(p1, p2)| p1 != p2) + .map(|(p1, p2)| BTreeSet::from([p1.clone(), p2.clone()])) + .collect(); + + let pairs: Vec<(Point, Point)> = pairs + .into_iter() + .map(|pair| { + let mut pair = pair.into_iter(); + let p1 = pair.next().unwrap(); + let p2 = pair.next().unwrap(); + (p1, p2) + }) + .collect(); + let distances: Vec = pairs + .par_iter() + .map(|(p1, p2)| { + let x = (p1.x as i64 - p2.x as i64).abs(); + let y = (p1.y as i64 - p2.y as i64).abs(); + (x + y) as usize + }) + .collect(); + + Ok(distances.par_iter().map(|&d| d as u64).sum()) } #[cfg(test)] @@ -12,7 +91,7 @@ mod tests { #[test_log::test] fn test_process() -> miette::Result<()> { let input = include_str!("../test-input.txt"); - assert_eq!(0, process(input)?); + assert_eq!(82000210, process(input)?); Ok(()) } }