#[path = "../lib.rs"] mod lib; #[derive(Debug, PartialEq, PartialOrd)] enum Dir { Up, Right, Down, Left, } fn parse_input() -> Vec> { return lib::iter_input().map(|line| line.bytes().collect()).collect(); } fn count_sides(perimeter: &Vec<(usize, usize, Dir)>) -> usize { let mut count = 0; for dir in [Dir::Up, Dir::Right, Dir::Down, Dir::Left] { let mut edges: Vec<(usize, usize)> = perimeter.iter() .filter(|(_x, _y, d)| *d == dir) .map(|(x, y, d)| match d { Dir::Up => (*y, *x), Dir::Right => (*x, *y), Dir::Down => (*y, *x), Dir::Left => (*x, *y), }).collect(); edges.sort(); for i in 0..edges.len() { if i == 0 { count += 1; continue; } let (x1, y1) = edges[i - 1]; let (x2, y2) = edges[i]; if x2 != x1 || y2 != y1 + 1 { count += 1; } } } return count; } fn main() { let map = parse_input(); let h = map.len(); let w = map[0].len(); let mut seen = vec![vec![false; w]; h]; let mut sum1 = 0; let mut sum2 = 0; for y0 in 0..map.len() { for x0 in 0..map[0].len() { if seen[y0][x0] { continue; } let mut area = 0; let mut perimeter = vec![]; let mut queue = vec![(x0, y0)]; while let Some((x, y)) = queue.pop() { if seen[y][x] { continue; } area += 1; if x > 0 && map[y][x - 1] == map[y][x] { queue.push((x - 1, y)); } else { perimeter.push((x, y, Dir::Left)); } if x + 1 < w && map[y][x + 1] == map[y][x] { queue.push((x + 1, y)); } else { perimeter.push((x, y, Dir::Right)); } if y > 0 && map[y - 1][x] == map[y][x] { queue.push((x, y - 1)); } else { perimeter.push((x, y, Dir::Up)); } if y + 1 < h && map[y + 1][x] == map[y][x] { queue.push((x, y + 1)); } else { perimeter.push((x, y, Dir::Down)); } seen[y][x] = true; } sum1 += area * perimeter.len(); sum2 += area * count_sides(&perimeter); } } println!("part1: {}", sum1); println!("part2: {}", sum2); }