Made my initial solution work

This commit is contained in:
Dreaded_X 2023-12-10 21:18:48 +01:00
parent 7734633c9f
commit 058653a3d9
Signed by: Dreaded_X
GPG Key ID: 5A0CBFE3C3377FAA

View File

@ -1,6 +1,6 @@
#![feature(test)] #![feature(test)]
use core::panic; use core::panic;
use std::collections::HashMap; use std::collections::{HashMap, VecDeque};
use anyhow::Result; use anyhow::Result;
use aoc::Solver; use aoc::Solver;
@ -180,46 +180,51 @@ impl Maze {
} }
} }
// #[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
// enum Loop { enum Loop {
// North, North,
// East, East,
// South, South,
// West, West,
// Inner, Inner,
// } }
//
// impl Loop { impl Loop {
// fn from(direction: (isize, isize)) -> Self { fn from(direction: (isize, isize)) -> Self {
// match direction { match direction {
// (0, -1) => Self::North, (0, -1) => Self::North,
// (1, 0) => Self::East, (1, 0) => Self::East,
// (0, 1) => Self::South, (0, 1) => Self::South,
// (-1, 0) => Self::West, (-1, 0) => Self::West,
// _ => unreachable!("Invalid direction"), _ => unreachable!("Invalid direction"),
// } }
// } }
//
// fn offset(&self) -> (isize, isize) { fn offset(&self) -> (isize, isize) {
// match self { match self {
// Loop::North => (0, -1), Loop::North => (0, -1),
// Loop::East => (1, 0), Loop::East => (1, 0),
// Loop::South => (0, 1), Loop::South => (0, 1),
// Loop::West => (-1, 0), Loop::West => (-1, 0),
// Loop::Inner => (0, 0), Loop::Inner => (0, 0),
// } }
// } }
// } }
//
// fn flood_fill(position: (isize, isize), map: &mut HashMap<(isize, isize), Loop>) { fn flood_fill(position: (isize, isize), map: &mut HashMap<(isize, isize), Loop>) {
// if map.get(&position).is_none() { let mut queue = VecDeque::new();
// map.insert(position, Loop::Inner); queue.push_back(position);
//
// for direction in DIRECTIONS { while let Some(position) = queue.pop_front() {
// flood_fill((position.0 + direction.0, position.1 + direction.1), map) if map.get(&position).is_none() {
// } map.insert(position, Loop::Inner);
// }
// } for direction in DIRECTIONS {
queue.push_back((position.0 + direction.0, position.1 + direction.1));
}
}
}
}
static DIRECTIONS: [(isize, isize); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)]; static DIRECTIONS: [(isize, isize); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)];
@ -292,10 +297,11 @@ impl aoc::Solver for Day {
} }
} }
// Alternate solution that works for the examples and is off-by-one for the actual input
fn part2(input: &str) -> Self::Output2 { fn part2(input: &str) -> Self::Output2 {
let mut position_start = (-1, -1); let mut position_start = (-1, -1);
let end_direction;
let maze: HashMap<(isize, isize), Maze> = input let mut maze: HashMap<(isize, isize), Maze> = input
.lines() .lines()
.enumerate() .enumerate()
.flat_map(|(y, line)| { .flat_map(|(y, line)| {
@ -311,11 +317,13 @@ impl aoc::Solver for Day {
}) })
.collect(); .collect();
let mut map = HashMap::new();
if position_start == (-1, -1) { if position_start == (-1, -1) {
panic!("No valid start in input"); panic!("No valid start in input");
} }
let mut map = HashMap::<(isize, isize), Maze>::new(); let mut sides = (0, 0);
let mut position_current = position_start; let mut position_current = position_start;
let mut position_previous = position_start; let mut position_previous = position_start;
@ -335,12 +343,17 @@ impl aoc::Solver for Day {
if let Some(tile_next) = maze.get(&position_next) { if let Some(tile_next) = maze.get(&position_next) {
if tile_current.connects(tile_next, direction) { if tile_current.connects(tile_next, direction) {
map.insert(position_current, *tile_current); map.insert(position_current, Loop::from(direction));
position_previous = position_current; position_previous = position_current;
position_current = position_next; position_current = position_next;
let s = tile_current.sides(direction);
sides.0 += s.0;
sides.1 += s.1;
if position_current == position_start { if position_current == position_start {
end_direction = Loop::from(direction);
break 'outer; break 'outer;
} }
@ -352,165 +365,151 @@ impl aoc::Solver for Day {
unreachable!("Unable to move forward..."); unreachable!("Unable to move forward...");
} }
// It appears that the start can always be replaced with an F // Replace the start with the correct piece
// Atleast in all the examples and my input let start = match (end_direction, map.get(&position_start).unwrap()) {
map.insert(position_start, Maze::SouthEast); (Loop::North, Loop::North) | (Loop::South, Loop::South) => Maze::Vertical,
(Loop::East, Loop::East) | (Loop::West, Loop::West) => Maze::Horizontal,
(Loop::South, Loop::East) | (Loop::West, Loop::North) => Maze::NorthEast,
(Loop::South, Loop::West) | (Loop::East, Loop::North) => Maze::NorthWest,
(Loop::East, Loop::South) | (Loop::North, Loop::West) => Maze::SouthWest,
(Loop::North, Loop::East) | (Loop::West, Loop::South) => Maze::SouthEast,
_ => unreachable!(),
};
maze.insert(position_start, start);
let bounds = ( // Add the sides of the start
input.lines().map(|line| line.len()).max().unwrap(), let start_sides = start.sides(map.get(&position_start).unwrap().offset());
input.lines().count(), sides.0 += start_sides.0;
); sides.1 += start_sides.1;
let mut count = 0; // Determine if the loop was travelled clockwise or anti clockwise
let mut in_loop = false; let clockwise = sides.0 > sides.1;
let mut maybe = None;
for y in 0..bounds.1 { let mut position_current = position_start;
for x in 0..bounds.0 { loop {
if let Some(entry) = map.get(&(x as isize, y as isize)) { let &direction = map.get(&position_current).unwrap();
match entry { let tile = maze.get(&position_current).unwrap();
Maze::Vertical => in_loop = !in_loop,
Maze::Horizontal => {} // Get neighbouring tiles that are inside of the loop
dir @ (Maze::NorthEast | Maze::SouthEast) => maybe = Some(*dir), let checks = match direction {
Maze::NorthWest => { Loop::North => match tile {
if maybe == Some(Maze::SouthEast) { Maze::Vertical => {
in_loop = !in_loop if clockwise {
} vec![(1, 0)]
} else {
vec![(-1, 0)]
} }
Maze::SouthWest => {
if maybe == Some(Maze::NorthEast) {
in_loop = !in_loop
}
}
Maze::Start => unreachable!("Start should have been replaced"),
} }
} else if in_loop { Maze::NorthEast => {
count += 1; if clockwise {
} vec![]
} else {
vec![(-1, 0), (0, 1)]
}
}
Maze::NorthWest => {
if clockwise {
vec![(1, 0), (0, 1)]
} else {
vec![]
}
}
_ => unreachable!(),
},
Loop::East => match tile {
Maze::Horizontal => {
if clockwise {
vec![(0, 1)]
} else {
vec![(0, -1)]
}
}
Maze::NorthEast => {
if clockwise {
vec![(-1, 0), (0, 1)]
} else {
vec![]
}
}
Maze::SouthEast => {
if clockwise {
vec![]
} else {
vec![(-1, 0), (0, -1)]
}
}
_ => unreachable!(),
},
Loop::South => match tile {
Maze::Vertical => {
if clockwise {
vec![(-1, 0)]
} else {
vec![(1, 0)]
}
}
Maze::SouthWest => {
if clockwise {
vec![]
} else {
vec![(0, -1), (1, 0)]
}
}
Maze::SouthEast => {
if clockwise {
vec![(0, -1), (-1, 0)]
} else {
vec![]
}
}
_ => unreachable!(),
},
Loop::West => match tile {
Maze::Horizontal => {
if clockwise {
vec![(0, -1)]
} else {
vec![(0, 1)]
}
}
Maze::NorthWest => {
if clockwise {
vec![]
} else {
vec![(1, 0), (0, 1)]
}
}
Maze::SouthWest => {
if clockwise {
vec![(1, 0), (0, -1)]
} else {
vec![]
}
}
_ => unreachable!(),
},
Loop::Inner => unreachable!("Loop should not contain Inner"),
};
// Perform a floodfill from those neighbouring tiles
for check in checks {
let check = (position_current.0 + check.0, position_current.1 + check.1);
flood_fill(check, &mut map);
}
let direction = direction.offset();
position_current.0 += direction.0;
position_current.1 += direction.1;
if position_current == position_start {
break;
} }
} }
count // Count how many tiles are marked as inner
map.iter()
.filter(|(_, &value)| value == Loop::Inner)
.count()
} }
// Alternate solution that works for the examples and is off-by-one for the actual input
// fn part2(input: &str) -> Self::Output2 {
// let mut position_start = (-1, -1);
// let maze: HashMap<(isize, isize), Maze> = input
// .lines()
// .enumerate()
// .flat_map(|(y, line)| {
// line.chars()
// .enumerate()
// .filter_map(|(x, c)| Maze::from(c).map(|maze| ((x as isize, y as isize), maze)))
// .inspect(|(position, maze)| {
// if *maze == Maze::Start {
// position_start = *position
// }
// })
// .collect::<Vec<_>>()
// })
// .collect();
//
// let mut map = HashMap::<(isize, isize), Loop>::new();
//
// if position_start == (-1, -1) {
// panic!("No valid start in input");
// }
//
// let mut sides = (0, 0);
//
// let mut position_current = position_start;
// let mut position_previous = position_start;
// 'outer: loop {
// let tile_current = maze.get(&position_current).unwrap();
//
// for direction in DIRECTIONS {
// let position_next = (
// position_current.0 + direction.0,
// position_current.1 + direction.1,
// );
//
// // We are now allowed to go back to the previous position
// if position_next == position_previous {
// continue;
// }
//
// if let Some(tile_next) = maze.get(&position_next) {
// if tile_current.connects(tile_next, direction) {
// map.insert(position_current, Loop::from(direction));
//
// position_previous = position_current;
// position_current = position_next;
//
// let s = tile_current.sides(direction);
// sides.0 += s.0;
// sides.1 += s.1;
//
// if position_current == position_start {
// break 'outer;
// }
//
// continue 'outer;
// }
// }
// }
//
// unreachable!("Unable to move forward...");
// }
//
// let clockwise = sides.0 > sides.1;
//
// let mut position_current = position_start;
// loop {
// let &direction = map.get(&position_current).unwrap();
//
// let check = match direction {
// Loop::North => {
// if clockwise {
// (1, 0)
// } else {
// (-1, 0)
// }
// }
// Loop::East => {
// if clockwise {
// (0, 1)
// } else {
// (0, -1)
// }
// }
// Loop::South => {
// if clockwise {
// (-1, 0)
// } else {
// (1, 0)
// }
// }
// Loop::West => {
// if clockwise {
// (0, -1)
// } else {
// (0, 1)
// }
// }
// Loop::Inner => unreachable!("Loop should not contain Inner"),
// };
// let check = (position_current.0 + check.0, position_current.1 + check.1);
//
// flood_fill(check, &mut map);
//
// let direction = direction.offset();
//
// position_current.0 += direction.0;
// position_current.1 += direction.1;
//
// if position_current == position_start {
// break;
// }
// }
//
// map.iter()
// .filter(|(_, &value)| value == Loop::Inner)
// .count()
// }
} }