#![allow(dead_code)] use num::complex::Complex as c; use num::Complex; use std::fs::File; use std::io::Read; #[derive(Debug, PartialEq, Clone, Copy)] enum Dir { Start, UD, LR, UR, UL, DL, DR, Ground, } #[derive(Debug, PartialEq, Clone, Copy)] enum Flood { Pipe, Empty, Full, } const LUT: [(Dir, Complex, Complex, char, char); 8] = [ (Dir::UD, c::new(0, 1), c::new(0, -1), '|', '│'), (Dir::LR, c::new(1, 0), c::new(-1, 0), '-', '─'), (Dir::UR, c::new(0, -1), c::new(1, 0), 'L', '└'), (Dir::UL, c::new(0, -1), c::new(-1, 0), 'J', '┘'), (Dir::DL, c::new(0, 1), c::new(-1, 0), '7', '┐'), (Dir::DR, c::new(0, 1), c::new(1, 0), 'F', '┌'), (Dir::Start, c::new(0, 0), c::new(0, 0), 'S', 'S'), (Dir::Ground, c::new(0, 0), c::new(0, 0), '.', ' '), ]; fn lookup(d: Dir) -> (Dir, Complex, Complex, char, char) { for i in 0..LUT.len() { if d == LUT[i].0 { return LUT[i].clone(); } } panic!(); } fn print_m(m: &Vec>) { for i in 0..m.len() { for j in 0..m[0].len() { print!("{}", lookup(m[i][j]).4); } println!(); } println!(); } fn print_m2(m: &Vec>) { for j in 0..m.len() { for i in 0..m[0].len() { let a = match m[j][i] { Flood::Pipe => '#', Flood::Empty => ' ', Flood::Full => '.', }; print!("{}", a); } println!(); } println!(); } fn find_start(m: &Vec>) -> Complex { for y in 0..m.len() { for x in 0..m[0].len() { if m[y][x] == Dir::Start { return (x as i32) + (y as i32) * c::i(); } } } panic!(); } fn next( mut pos: Complex, mut dir: Complex, m: &Vec>, ) -> (Complex, Complex) { pos += dir; let (_, a, b, _, _) = lookup(m[pos.im as usize][pos.re as usize]); dir *= -1; if dir == a { dir = b; } else if dir == b { dir = a; } else { // panic!(); } (pos, dir) } fn flood(mut m: Vec>) -> (Vec>, usize) { let mut changes = 0; for y in 1..m.len() - 1 { for x in 1..m[0].len() - 1 { if m[y][x] == Flood::Full { for (yy, xx) in [(y - 1, x), (y + 1, x), (y, x + 1), (y, x - 1)] { if m[yy][xx] == Flood::Empty { changes += 1; m[yy][xx] = Flood::Full; } } } } } (m, changes) } fn main() { // let filename = "in/day10.ref"; let filename = "in/day10.pzl"; let mut f = File::open(filename).expect("cannot open file"); let mut content = String::new(); f.read_to_string(&mut content).expect("cannot read file"); let lines = content.trim_end().split('\n'); let mut m1: Vec> = Vec::new(); for line in lines { let mut r = Vec::new(); for c in line.chars() { for m1 in LUT { if m1.3 == c { r.push(m1.0); } } } m1.push(r); } // print_m(&m1); let start = find_start(&m1); let mut pos = start; let mut dir = c::new(1, 0); let mut path: Vec<(usize, usize)> = Vec::new(); let mut res1 = 0; loop { path.push((pos.re as usize, pos.im as usize)); (pos, dir) = next(pos, dir, &m1); res1 += 1; if pos == start { break; } } path.push((pos.re as usize, pos.im as usize)); res1 /= 2; let mut m2: Vec> = vec![vec![Flood::Empty; 2 * m1[0].len() + 4]; 2 * m1.len() + 4]; for ((x0, y0), (x1, y1)) in path.iter().zip(path.iter().skip(1)) { m2[*y0 * 2 + 2][*x0 * 2 + 2] = Flood::Pipe; m2[*y0 + *y1 + 2][*x0 + *x1 + 2] = Flood::Pipe; } for y in 0..m2.len() { let l = m2[0].len() - 1; m2[y][0] = Flood::Full; m2[y][1] = Flood::Full; m2[y][l - 1] = Flood::Full; m2[y][l] = Flood::Full; } for x in 0..m2[0].len() { let l = m2.len() - 1; m2[0][x] = Flood::Full; m2[1][x] = Flood::Full; m2[l - 1][x] = Flood::Full; m2[l][x] = Flood::Full; } // print_m2(&m2); let mut changes = 1; while changes != 0 { (m2, changes) = flood(m2); } // print_m2(&m2); let mut res2 = 0; for y in (2..m2.len()).step_by(2) { for x in (2..m2[0].len()).step_by(2) { if m2[y][x] == Flood::Empty { res2 += 1; } } } println!("res1: {}", res1); println!("res2: {}", res2); assert_eq!(res1, 6778); assert_eq!(res2, 433); }