use std::collections::HashSet; #[path = "../lib.rs"] mod lib; const TOP: u8 = 1; const RIGHT: u8 = 2; const BOTTOM: u8 = 4; const LEFT: u8 = 8; fn cmp(a: u8, b: u8) -> bool { return a & b == b; } fn to_char(cell: u8) -> char { return if cmp(cell, LEFT | RIGHT) { '-' } else if cmp(cell, TOP | BOTTOM) { '|' } else if cmp(cell, TOP | RIGHT) { 'L' } else if cmp(cell, BOTTOM | RIGHT) { 'F' } else if cmp(cell, TOP | LEFT) { 'J' } else if cmp(cell, BOTTOM | LEFT) { '7' } else { '.' }; } fn parse_input() -> (Vec>, usize, usize) { let mut x0 = 0; let mut y0 = 0; let map: Vec> = lib::iter_input().enumerate() .map(|(y, line)| { line.chars().enumerate() .map(|(x, c)| match c { '-' => LEFT | RIGHT, '|' => TOP | BOTTOM, 'L' => TOP | RIGHT, 'F' => BOTTOM | RIGHT, 'J' => TOP | LEFT, '7' => BOTTOM | LEFT, 'S' => { x0 = x; y0 = y; return 0; }, '.' => 0, _ => unreachable!(), }) .collect() }) .collect(); return (map, x0, y0); } fn get_pipe(map: &Vec>, x0: usize, y0: usize, dir0: u8) -> HashSet<(usize, usize)> { let mut pipe = HashSet::new(); let mut x = x0; let mut y = y0; let mut dir = dir0; while pipe.len() == 0 || x != x0 || y != y0 { match map[y][x] - dir { TOP => { y -= 1; dir = BOTTOM; }, RIGHT => { x += 1; dir = LEFT; }, BOTTOM => { y += 1; dir = TOP; }, LEFT => { x -= 1; dir = RIGHT; }, _ => unreachable!(), } pipe.insert((x, y)); } return pipe; } fn count_inside(map: &Vec>, pipe: &HashSet<(usize, usize)>) -> usize { let mut count = 0; let mut inside; let mut enter_direction; for y in 0..map.len() { inside = false; enter_direction = 0; for x in 0..map[y].len() { if pipe.contains(&(x, y)) { let vertical = map[y][x] & (TOP | BOTTOM); if vertical == TOP | BOTTOM { inside = !inside; } else if vertical != 0 { if enter_direction == 0 { enter_direction = vertical; } else { if enter_direction != vertical { inside = !inside; } enter_direction = 0; } } print!("{}", to_char(map[y][x])); } else if inside { count += 1; print!("."); } else { print!(" "); } } println!(""); } return count; } fn main() { let (mut map, x0, y0) = parse_input(); let mut dir0 = 0; if x0 > 0 && map[y0][x0 - 1] & RIGHT != 0 { dir0 = LEFT; map[y0][x0] |= LEFT; } if y0 > 0 && map[y0 - 1][x0] & BOTTOM != 0 { dir0 = TOP; map[y0][x0] |= TOP; } if y0 < map.len() - 1 && map[y0 + 1][x0] & TOP != 0 { dir0 = BOTTOM; map[y0][x0] |= BOTTOM; } if x0 < map[0].len() - 1 && map[y0][x0 + 1] & LEFT != 0 { dir0 = RIGHT; map[y0][x0] |= RIGHT; } let pipe = get_pipe(&map, x0, y0, dir0); let count = count_inside(&map, &pipe); println!("part1: {}", pipe.len() / 2); println!("part2: {}", count); }