Made my initial solution work
This commit is contained in:
parent
7734633c9f
commit
058653a3d9
|
@ -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()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user