From 2027cb4149c34b231a660f28b3b206b8b9570fa4 Mon Sep 17 00:00:00 2001 From: tom-anders <13141438+tom-anders@users.noreply.github.com> Date: Fri, 6 Dec 2024 09:56:07 +0100 Subject: [PATCH] refactor: clean up day 6 --- day6/src/main.rs | 75 +++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 49 deletions(-) diff --git a/day6/src/main.rs b/day6/src/main.rs index 218eebb..865295a 100644 --- a/day6/src/main.rs +++ b/day6/src/main.rs @@ -1,75 +1,52 @@ -#![feature(hash_set_entry)] - -use std::collections::{HashSet, hash_set::Entry}; +use std::collections::HashSet; use aoc_derive::aoc_main; use grid::Grid; +use itertools::Itertools; use math::Vec2D; use utils::*; -fn part1_visited(map: &Grid, start: Vec2D) -> HashSet { +fn iterate(map: &Grid, start: Vec2D) -> Option> { let mut pos = start; - let mut heading = Vec2D::new(0, -1); - let mut visited = HashSet::new(); + loop { - visited.insert(pos); + if visited.contains(&(pos, heading)) { + return None; // loop detected + } + visited.insert((pos, heading)); match map.get(pos + heading) { None => break, Some(&'#') => heading = heading.rotated_right(), - _ => { - pos += heading; - } - } - } - visited -} - -fn check_obstruction(map: &Grid, mut pos: Vec2D) -> bool { - let mut visited = HashSet::new(); - let mut heading = Vec2D::new(0, -1); - visited.insert((pos, heading)); - loop { - match map.get(pos + heading) { - None => { - return false; - } - Some(&'#') => { - heading = heading.rotated_right(); - } - _ => { - pos += heading; - } - } - match visited.entry((pos, heading)) { - Entry::Vacant(entry) => entry.insert(), - Entry::Occupied(_) => return true, + _ => pos += heading, } } -} - -fn part2(mut map: Grid, start: Vec2D, to_check: &HashSet) -> usize { - to_check - .iter() - .filter(|&&block| { - map[block] = '#'; - let res = check_obstruction(&map, start); - map[block] = '.'; - res - }) - .count() + Some(visited) } #[aoc_main] fn solve(input: Input) -> impl Into { - let map = input.char_grid(); + let mut map = input.char_grid(); let start = map.iter().find_map(|(pos, &c)| (c == '^').then_some(pos)).unwrap(); - let visited = part1_visited(&map, start); + let visited: HashSet<_> = + iterate(&map, start).unwrap().into_iter().map(|(pos, _)| pos).unique().collect(); + + let part1 = visited.len(); + + let part2 = visited + .into_iter() + .filter(|&pos| { + map[pos] = '#'; + let res = iterate(&map, start); + map[pos] = '.'; + res.is_none() + }) + .count(); - (visited.len(), part2(map, start, &visited)) + (part1, part2) } #[cfg(test)]