diff --git a/aoc_2023/src/day_10.rs b/aoc_2023/src/day_10.rs index 01c028f..d111777 100644 --- a/aoc_2023/src/day_10.rs +++ b/aoc_2023/src/day_10.rs @@ -8,6 +8,8 @@ type Pos = Vec2; pub struct Day10; +// This is a mess, but it took me a while to figure out -- so I shall clean it up later (probs like 12 hours) + impl Solution for Day10 { fn name(&self) -> &'static str { "Pipe Maze" @@ -60,10 +62,82 @@ impl Solution for Day10 { (len / 2).into() } + // 501 fn part_b(&self, input: &str) -> Answer { let maze = parse(input); - let mut pos = maze.start; + let (org_x, org_y) = (maze.segments[0].len(), maze.segments.len()); + let mut org_walls = 0; + + let mut start = maze.start; + let mut segments = maze + .segments + .iter() + .enumerate() + .map(|(y, line)| { + let mut new = vec![Vec::with_capacity(line.len() * 2); 2]; + + for (x, c) in line.iter().enumerate() { + if c != &'.' { + org_walls += 1; + } + + match c { + '|' => { + new[0].extend_from_slice(&['|', '.']); + new[1].extend_from_slice(&['|', '.']); + } + '-' => { + new[0].extend_from_slice(&['-', '-']); + new[1].extend_from_slice(&['.', '.']); + } + '7' => { + new[0].extend_from_slice(&['7', '.']); + new[1].extend_from_slice(&['|', '.']); + } + 'F' => { + new[0].extend_from_slice(&['F', '-']); + new[1].extend_from_slice(&['|', '.']); + } + 'L' => { + new[0].extend_from_slice(&['L', '-']); + new[1].extend_from_slice(&['.', '.']); + } + 'J' => { + new[0].extend_from_slice(&['J', '.']); + new[1].extend_from_slice(&['.', '.']); + } + 'S' => { + start = vector!(x * 2, y * 2); + new[0].extend_from_slice(&[ + 'S', + match maze.segments[y][x + 1] { + '-' | '7' | 'J' => '-', + _ => '.', + }, + ]); + new[1].extend_from_slice(&[ + match maze.segments[y + 1][x] { + '|' | 'L' | 'J' => '|', + _ => '.', + }, + '.', + ]); + } + '.' => { + new[0].extend_from_slice(&['.', '.']); + new[1].extend_from_slice(&['.', '.']); + } + _ => unreachable!(), + } + } + + new + }) + .flatten() + .collect::>(); + + let mut pos = dbg!(start); let mut dir = Direction::Right; let mut walls = HashSet::new(); @@ -76,7 +150,7 @@ impl Solution for Day10 { Direction::Right => vector!(pos.x() + 1, pos.y()), }; - let pipe = maze.segments[pos.y()][pos.x()]; + let pipe = segments[pos.y()][pos.x()]; dir = match pipe { '|' | '-' => dir, '7' => match dir { @@ -104,12 +178,44 @@ impl Solution for Day10 { }; } + for y in 0..segments.len() { + for x in 0..segments[0].len() { + if !walls.contains(&vector!(x, y)) && segments[y][x] != '.' { + segments[y][x] = '.'; + + if x % 2 == 0 && y % 2 == 0 { + org_walls -= 1; + } + } + } + } + + for line in segments.iter() { + for c in line.iter() { + print!("{}", c); + } + println!(); + } + println!(); + // Flood fill to find the number of reachable not reachable from the outside + let mut stack = vec![]; + + // Add perimeter to stack + for x in 0..segments[0].len() { + stack.push(vector!(x, 0)); + stack.push(vector!(x, segments.len() - 1)); + } + + for y in 0..segments.len() { + stack.push(vector!(0, y)); + stack.push(vector!(segments[0].len() - 1, y)); + } + + stack.retain(|x| segments[x.y()][x.x()] == '.'); - let pos = vector!(maze.segments[0].len(), maze.segments.len()); - // let pos = vector!(0, 0); - let mut stack = vec![pos]; let mut visited = HashSet::new(); + let mut outside = 0; while let Some(pos) = stack.pop() { let [x, y] = [pos.x() as isize, pos.y() as isize]; @@ -118,10 +224,10 @@ impl Solution for Day10 { vector!(x, y + 1), vector!(x - 1, y), vector!(x + 1, y), - vector!(x + 1, y + 1), - vector!(x - 1, y + 1), - vector!(x + 1, y - 1), - vector!(x - 1, y - 1), + // vector!(x + 1, y + 1), + // vector!(x - 1, y + 1), + // vector!(x + 1, y - 1), + // vector!(x - 1, y - 1), ] { if pos.x() < 0 || pos.y() < 0 { continue; @@ -129,22 +235,33 @@ impl Solution for Day10 { let pos = vector!(pos.x() as usize, pos.y() as usize); - let in_bounds = - pos.x() < maze.segments[0].len() + 2 && pos.y() < maze.segments.len() + 2; - if !walls.contains(&(pos + vector!(1, 1))) && in_bounds && !visited.contains(&pos) { + let in_bounds = pos.x() < segments[0].len() && pos.y() < segments.len(); + if in_bounds && !visited.contains(&pos) && segments[pos.y()][pos.x()] == '.' { stack.push(pos); visited.insert(pos); + + if pos.x() % 2 == 0 && pos.y() % 2 == 0 { + outside += 1; + } } } } - dbg!( - (maze.segments.len() + 2) * (maze.segments[0].len() + 2), - visited.len(), - walls.len() - ); - - (((maze.segments.len() + 2) * (maze.segments[0].len() + 2)) - visited.len() - walls.len()) - .into() + + for (y, line) in segments.iter().enumerate() { + for (x, c) in line.iter().enumerate() { + if !visited.contains(&vector!(x, y)) { + print!("{}", c); + } else { + print!(" "); + } + } + println!(); + } + + dbg!(org_x * org_y, outside, org_walls); + dbg!(org_x * org_y - org_walls); + + (org_x * org_y - outside - org_walls).into() } } @@ -193,16 +310,16 @@ mod test { "}; const CASE_B: &str = indoc! {" - .F----7F7F7F7F-7.... - .|F--7||||||||FJ.... - .||.FJ||||||||L7.... - FJL7L7LJLJ||LJ.L-7.. - L--J.L7...LJS7F-7L7. - ....F-J..F7FJ|L7L7L7 - ....L7.F7||L7|.L7L7| - .....|FJLJ|FJ|F7|.LJ - ....FJL-7.||.||||... - ....L---J.LJ.LJLJ... + FF7FSF7F7F7F7F7F---7 + L|LJ||||||||||||F--J + FL-7LJLJ||||||LJL-77 + F--JF--7||LJLJ7F7FJ- + L---JF-JLJ.||-FJLJJ7 + |F|F-JF---7F7-L7L|7| + |FFJF7L7F-JF7|JL---7 + 7-L-JL7||F7|L7F-7F7| + L.L7LFJ|||||FJL7||LJ + L7JLJL-JLJLJL--JLJ.L "}; #[test] @@ -212,6 +329,6 @@ mod test { #[test] fn part_b() { - assert_eq!(Day10.part_b(CASE_B), 8.into()); + assert_eq!(Day10.part_b(CASE_B), 10.into()); } }