|
| 1 | +//! # A Regular Map |
| 2 | +//! |
| 3 | +//! Simple solution taking advantage of a controversial property of the input. After taking any |
| 4 | +//! branch it's assumed that we can return to the pre-branch position. This does *not* hold for |
| 5 | +//! general inputs, as it's easy to construct paths which violate this constraint. |
| 6 | +//! |
| 7 | +//! We use a stack to save the position before a branch, pushing whenever an opening `(` is |
| 8 | +//! encountered then popping whenever the closing `)` is found. Additionally we assume that |
| 9 | +//! the location will never move more than 55 rooms from the starting location in order to use |
| 10 | +//! a fixed size array to hold the minimum distance to any room. |
| 11 | +type Input = (u32, usize); |
| 12 | + |
| 13 | +pub fn parse(input: &str) -> Input { |
| 14 | + explore(input) |
| 15 | +} |
| 16 | + |
| 17 | +pub fn part1(input: &Input) -> u32 { |
| 18 | + input.0 |
| 19 | +} |
| 20 | + |
| 21 | +pub fn part2(input: &Input) -> usize { |
| 22 | + input.1 |
| 23 | +} |
| 24 | + |
| 25 | +fn explore(input: &str) -> Input { |
| 26 | + // Start in the center. |
| 27 | + let mut index = 6105; |
| 28 | + // 55 in each direction, gives a width and height of 110, for a total size of 12,100. |
| 29 | + let mut grid = vec![u32::MAX; 12_100]; |
| 30 | + let mut stack = Vec::with_capacity(500); |
| 31 | + let mut part_one = 0; |
| 32 | + |
| 33 | + grid[index] = 0; |
| 34 | + |
| 35 | + for b in input.bytes() { |
| 36 | + let distance = grid[index]; |
| 37 | + |
| 38 | + match b { |
| 39 | + b'(' => stack.push(index), |
| 40 | + b'|' => index = stack[stack.len() - 1], |
| 41 | + b')' => index = stack.pop().unwrap(), |
| 42 | + b'N' => index -= 110, |
| 43 | + b'S' => index += 110, |
| 44 | + b'W' => index -= 1, |
| 45 | + b'E' => index += 1, |
| 46 | + _ => (), |
| 47 | + } |
| 48 | + |
| 49 | + grid[index] = grid[index].min(distance + 1); |
| 50 | + part_one = part_one.max(grid[index]); |
| 51 | + } |
| 52 | + |
| 53 | + let part_two = grid.iter().filter(|d| (1000..u32::MAX).contains(d)).count(); |
| 54 | + (part_one, part_two) |
| 55 | +} |
0 commit comments