Advent of Code solutions
at main 95 lines 2.9 kB view raw
1use std::collections::{HashMap, HashSet, VecDeque}; 2 3use advent_core::{day_stuff, ex_for_day, Day}; 4use utils::{dir::Direction, pos::Position, tiles}; 5 6pub struct Day7; 7 8tiles!(Tile, [ 9 'S' => Start, 10 '^' => Splitter, 11 '.' => Empty, 12]); 13 14type Grid = utils::grid::Grid<Tile>; 15 16impl Day for Day7 { 17 day_stuff!(7, "21", "40", Grid); 18 19 fn part_1(input: Self::Input) -> Option<String> { 20 let (start, _) = input.iter().find(|(_, t)| **t == Tile::Start).unwrap(); 21 let mut queue = VecDeque::<Position>::new(); 22 let mut seen = HashSet::<Position>::with_capacity(input.size().1); 23 24 queue.push_back(start); 25 26 let mut splits = 0; 27 28 while let Some(pos) = queue.pop_front() { 29 if seen.contains(&pos) { 30 continue; 31 } 32 seen.insert(pos); 33 let next_pos = Position::new(pos.x, pos.y + 1); 34 match input.get(next_pos) { 35 Some(Tile::Splitter) => { 36 splits += 1; 37 queue.push_back(Position::new(pos.x + 1, pos.y)); 38 queue.push_back(Position::new(pos.x - 1, pos.y)); 39 } 40 Some(Tile::Empty) => { 41 queue.push_back(next_pos); 42 } 43 _ => {} 44 } 45 } 46 47 Some(splits.to_string()) 48 } 49 50 fn part_2(input: Self::Input) -> Option<String> { 51 let (start, _) = input.iter().find(|(_, t)| **t == Tile::Start).unwrap(); 52 let mut queue = VecDeque::<Position>::new(); 53 let mut seen = HashMap::<Position, usize>::new(); 54 55 seen.insert(start, 1); 56 queue.push_front(start); 57 58 let mut splits = 0; 59 60 while let Some(pos) = queue.pop_front() { 61 let amnt = seen.get(&pos).copied().unwrap_or_default(); 62 let next_pos = pos.move_dir(Direction::South); 63 match input.get(next_pos) { 64 Some(Tile::Splitter) => { 65 for (next_pos, _) in next_pos.relatives(&[Direction::West, Direction::East]) { 66 if let Some(curr) = seen.get_mut(&next_pos) { 67 *curr += amnt; 68 } else { 69 seen.insert(next_pos, amnt); 70 queue.push_back(next_pos); 71 } 72 } 73 } 74 Some(Tile::Empty) => { 75 if let Some(curr) = seen.get_mut(&next_pos) { 76 *curr += amnt; 77 } else { 78 seen.insert(next_pos, amnt); 79 queue.push_back(next_pos); 80 } 81 } 82 None => { 83 splits += amnt; 84 } 85 _ => {} 86 } 87 } 88 89 Some(splits.to_string()) 90 } 91 92 fn parse_input(input: &str) -> Self::Input { 93 Grid::parse(input) 94 } 95}