diff options
author | Jesse Luehrs <doy@tozt.net> | 2022-12-18 00:51:34 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2022-12-18 00:51:34 -0500 |
commit | 6a25cc7799fbe482b4d943e46332f18f483c788b (patch) | |
tree | 8ebc4ec984ca108da6706c278f5c86206d3701fa /src/bin | |
parent | a8dcdf90118b210ff751e76e1e332bbde87575d7 (diff) | |
download | advent-of-code-6a25cc7799fbe482b4d943e46332f18f483c788b.tar.gz advent-of-code-6a25cc7799fbe482b4d943e46332f18f483c788b.zip |
day 18
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/2022/day18.rs | 130 | ||||
-rw-r--r-- | src/bin/2022/main.rs | 2 |
2 files changed, 132 insertions, 0 deletions
diff --git a/src/bin/2022/day18.rs b/src/bin/2022/day18.rs new file mode 100644 index 0000000..35944f1 --- /dev/null +++ b/src/bin/2022/day18.rs @@ -0,0 +1,130 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +use advent_of_code::prelude::*; + +pub fn parse(fh: File) -> Result<Vec<(i64, i64, i64)>> { + Ok(parse::raw_lines(fh) + .map(|s| { + let mut parts = s.split(','); + ( + parts.next().unwrap().parse().unwrap(), + parts.next().unwrap().parse().unwrap(), + parts.next().unwrap().parse().unwrap(), + ) + }) + .collect()) +} + +pub fn part1(points: Vec<(i64, i64, i64)>) -> Result<i64> { + let mut total = 0; + for p in &points { + let mut area = 6; + for neighbor in [ + (p.0 - 1, p.1, p.2), + (p.0 + 1, p.1, p.2), + (p.0, p.1 - 1, p.2), + (p.0, p.1 + 1, p.2), + (p.0, p.1, p.2 - 1), + (p.0, p.1, p.2 + 1), + ] { + if points.contains(&neighbor) { + area -= 1; + } + } + total += area; + } + Ok(total) +} + +pub fn part2(points: Vec<(i64, i64, i64)>) -> Result<i64> { + let mut all_neighbors = HashSet::new(); + for p in &points { + for neighbor in [ + (p.0 - 1, p.1, p.2), + (p.0 + 1, p.1, p.2), + (p.0, p.1 - 1, p.2), + (p.0, p.1 + 1, p.2), + (p.0, p.1, p.2 - 1), + (p.0, p.1, p.2 + 1), + ] { + if !points.contains(&neighbor) { + all_neighbors.insert(neighbor); + } + } + } + + let bounds = ( + (points.iter().map(|p| p.0).min().unwrap() - 1) + ..=(points.iter().map(|p| p.0).max().unwrap() + 1), + (points.iter().map(|p| p.1).min().unwrap() - 1) + ..=(points.iter().map(|p| p.1).max().unwrap() + 1), + (points.iter().map(|p| p.2).min().unwrap() - 1) + ..=(points.iter().map(|p| p.2).max().unwrap() + 1), + ); + let mut visited = HashSet::new(); + let mut to_visit = + vec![(*bounds.0.start(), *bounds.1.start(), *bounds.2.start())]; + while let Some(p) = to_visit.pop() { + visited.insert(p); + let neighbors = [ + (p.0 - 1, p.1, p.2), + (p.0 + 1, p.1, p.2), + (p.0, p.1 - 1, p.2), + (p.0, p.1 + 1, p.2), + (p.0, p.1, p.2 - 1), + (p.0, p.1, p.2 + 1), + ]; + to_visit.extend( + neighbors + .iter() + .filter(|p| in_bounds(**p, &bounds)) + .filter(|p| !visited.contains(p)) + .filter(|p| !points.contains(p)), + ) + } + + let mut total = 0; + for p in &points { + let mut area = 6; + for neighbor in [ + (p.0 - 1, p.1, p.2), + (p.0 + 1, p.1, p.2), + (p.0, p.1 - 1, p.2), + (p.0, p.1 + 1, p.2), + (p.0, p.1, p.2 - 1), + (p.0, p.1, p.2 + 1), + ] { + if points.contains(&neighbor) || !visited.contains(&neighbor) { + area -= 1; + } + } + total += area; + } + Ok(total) +} + +fn in_bounds( + p: (i64, i64, i64), + bounds: &( + std::ops::RangeInclusive<i64>, + std::ops::RangeInclusive<i64>, + std::ops::RangeInclusive<i64>, + ), +) -> bool { + bounds.0.contains(&p.0) + && bounds.1.contains(&p.1) + && bounds.2.contains(&p.2) +} + +#[test] +fn test() { + assert_eq!( + part1(parse(parse::data(2022, 18).unwrap()).unwrap()).unwrap(), + 4608 + ); + assert_eq!( + part2(parse(parse::data(2022, 18).unwrap()).unwrap()).unwrap(), + 2652 + ); +} diff --git a/src/bin/2022/main.rs b/src/bin/2022/main.rs index 744516a..6c02180 100644 --- a/src/bin/2022/main.rs +++ b/src/bin/2022/main.rs @@ -28,6 +28,7 @@ mod day14; mod day15; mod day16; mod day17; +mod day18; // NEXT MOD #[paw::main] @@ -51,6 +52,7 @@ fn main(opt: Opt) -> Result<()> { 15 => advent_of_code::day!(2022, opt.day, opt.puzzle, day15), 16 => advent_of_code::day!(2022, opt.day, opt.puzzle, day16), 17 => advent_of_code::day!(2022, opt.day, opt.puzzle, day17), + 18 => advent_of_code::day!(2022, opt.day, opt.puzzle, day18), // NEXT PART _ => panic!("unknown day {}", opt.day), } |