#[path = "../lib.rs"] mod lib; enum Cell { Empty, SplitVertical, SplitHorizontal, MirrorLeft, MirrorRight, } #[derive(Copy, Clone)] enum Dir { Right = 1, Left = 2, Up = 4, Down = 8, } fn parse_input() -> Vec> { return lib::iter_input() .map(|line| { return line .bytes() .map(|b| match b { b'.' => Cell::Empty, b'|' => Cell::SplitVertical, b'-' => Cell::SplitHorizontal, b'\\' => Cell::MirrorLeft, b'/' => Cell::MirrorRight, _ => unreachable!(), }) .collect(); }) .collect(); } fn push(map: &Vec>, queue: &mut Vec<(usize, usize, Dir)>, x: usize, y: usize, dir: Dir) { match dir { Dir::Left => { if x > 0 { queue.push((x - 1, y, dir)); } } Dir::Right => { if x + 1 < map[0].len() { queue.push((x + 1, y, dir)); } } Dir::Up => { if y > 0 { queue.push((x, y - 1, dir)); } } Dir::Down => { if y + 1 < map.len() { queue.push((x, y + 1, dir)); } } }; } fn count(map: &Vec>, start: (usize, usize, Dir)) -> usize { let mut visited = vec![vec![0; map[0].len()]; map.len()]; let mut queue = vec![start]; while let Some((x, y, dir)) = queue.pop() { if visited[y][x] & (dir as u8) != 0 { continue; } match map[y][x] { Cell::Empty => { push(&map, &mut queue, x, y, dir); } Cell::SplitHorizontal => { if visited[y][x] != 0 { continue; } match dir { Dir::Right | Dir::Left => { push(&map, &mut queue, x, y, dir); } Dir::Up | Dir::Down => { push(&map, &mut queue, x, y, Dir::Left); push(&map, &mut queue, x, y, Dir::Right); } }; } Cell::SplitVertical => { if visited[y][x] != 0 { continue; } match dir { Dir::Up | Dir::Down => { push(&map, &mut queue, x, y, dir); } Dir::Left | Dir::Right => { push(&map, &mut queue, x, y, Dir::Up); push(&map, &mut queue, x, y, Dir::Down); } }; } Cell::MirrorRight => match dir { Dir::Up => push(&map, &mut queue, x, y, Dir::Right), Dir::Right => push(&map, &mut queue, x, y, Dir::Up), Dir::Down => push(&map, &mut queue, x, y, Dir::Left), Dir::Left => push(&map, &mut queue, x, y, Dir::Down), }, Cell::MirrorLeft => match dir { Dir::Down => push(&map, &mut queue, x, y, Dir::Right), Dir::Left => push(&map, &mut queue, x, y, Dir::Up), Dir::Up => push(&map, &mut queue, x, y, Dir::Left), Dir::Right => push(&map, &mut queue, x, y, Dir::Down), }, } visited[y][x] |= dir as u8; } let mut sum = 0; for y in 0..map.len() { for x in 0..map[0].len() { if visited[y][x] != 0 { sum += 1; } } } return sum; } fn main() { let map = parse_input(); let sum1 = count(&map, (0, 0, Dir::Right)); println!("part1: {}", sum1); let mut sum2 = 0; for x in 0..map[0].len() { sum2 = sum2.max(count(&map, (x, 0, Dir::Down))); sum2 = sum2.max(count(&map, (x, map.len() - 1, Dir::Up))); } for y in 0..map.len() { sum2 = sum2.max(count(&map, (0, y, Dir::Right))); sum2 = sum2.max(count(&map, (map[0].len() - 1, y, Dir::Left))); } println!("part2: {}", sum2); }