2022 - Day 22

This commit is contained in:
Dreaded_X 2022-12-23 01:10:54 +01:00
parent 80da5eb67e
commit 932cd5af60
Signed by: Dreaded_X
GPG Key ID: 76BDEC4E165D8AD9

View File

@ -27,6 +27,10 @@ mod tests {
fn part2_test1() -> Result<()> { fn part2_test1() -> Result<()> {
Day::test(Day::part2, "test-1", 5031) Day::test(Day::part2, "test-1", 5031)
} }
#[test]
fn part2_solution() -> Result<()> {
Day::test(Day::part2, "input", 37415)
}
// Benchmarks // Benchmarks
extern crate test; extern crate test;
@ -212,7 +216,7 @@ impl Map {
for m in moves { for m in moves {
self.step(m.0); self.step(m.0);
if let Some(clockwise) = m.1 { if let Some(clockwise) = m.1 {
self.rotate(clockwise); self.player.direction.rotate(clockwise);
} }
} }
} }
@ -239,7 +243,7 @@ impl Map {
let neighbour = self.get_neighbour(&np.plane, &np.direction); let neighbour = self.get_neighbour(&np.plane, &np.direction);
np.plane = neighbour.0; np.plane = neighbour.0;
// Update the coordinates of the player // Apply the correct transform to the player position
np = neighbour.1(np); np = neighbour.1(np);
} }
}, },
@ -253,7 +257,7 @@ impl Map {
let neighbour = self.get_neighbour(&np.plane, &np.direction); let neighbour = self.get_neighbour(&np.plane, &np.direction);
np.plane = neighbour.0; np.plane = neighbour.0;
// Update the coordinates of the player // Apply the correct transform to the player position
np = neighbour.1(np); np = neighbour.1(np);
} else { } else {
np.position.x -= 1; np.position.x -= 1;
@ -270,7 +274,7 @@ impl Map {
let neighbour = self.get_neighbour(&np.plane, &np.direction); let neighbour = self.get_neighbour(&np.plane, &np.direction);
np.plane = neighbour.0; np.plane = neighbour.0;
// Update the coordinates of the player // Apply the correct transform to the player position
np = neighbour.1(np); np = neighbour.1(np);
} }
}, },
@ -284,7 +288,7 @@ impl Map {
let neighbour = self.get_neighbour(&np.plane, &np.direction); let neighbour = self.get_neighbour(&np.plane, &np.direction);
np.plane = neighbour.0; np.plane = neighbour.0;
// Update the coordinates of the player // Apply the correct transform to the player position
np = neighbour.1(np); np = neighbour.1(np);
} else { } else {
np.position.y -= 1; np.position.y -= 1;
@ -307,10 +311,6 @@ impl Map {
} }
} }
fn rotate(&mut self, clockwise: bool) {
self.player.direction.rotate(clockwise);
}
fn score(&self) -> usize { fn score(&self) -> usize {
1000 * (self.player.plane.y*self.size + self.player.position.y + 1) + 4 * (self.player.plane.x*self.size + self.player.position.x + 1) + (usize::from(&self.player.direction)) 1000 * (self.player.plane.y*self.size + self.player.position.y + 1) + 4 * (self.player.plane.x*self.size + self.player.position.x + 1) + (usize::from(&self.player.direction))
} }
@ -334,7 +334,6 @@ impl Map {
{ {
let y_neighbour = (0..PLANES).cycle().skip(y+1).take(PLANES).find(|y| self.planes[*y][x].is_some()).unwrap(); let y_neighbour = (0..PLANES).cycle().skip(y+1).take(PLANES).find(|y| self.planes[*y][x].is_some()).unwrap();
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(x, y_neighbour), Rc::new(Box::new(move |mut p: Player| { self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(x, y_neighbour), Rc::new(Box::new(move |mut p: Player| {
// This happens post move
p.position.y = 0; p.position.y = 0;
return p; return p;
})))); }))));
@ -363,9 +362,393 @@ impl Map {
} }
} }
fn fill_neighbours_part2(&mut self) { // Setup the connection to the neighbours for the test case
// @TODO Automatically construct this instead of manually figuring out where every edge leads
fn fill_neighbours_part2_test(&mut self) {
let size = self.size;
{ {
let (x, y) = (2, 0);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(0, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size - p.position.x - 1;
p.position.y = 0;
p.direction = Direction::Down;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = p.position.y;
p.position.y = 0;
p.direction = Direction::Down;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(2, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = 0;
p.direction = Direction::Down;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(3, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.y - 1;
p.position.y = size-1;
p.direction = Direction::Left;
return p;
}))));
}
{
let (x, y) = (0, 1);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size - p.position.x - 1;
p.position.y = 0;
p.direction = Direction::Down;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(3, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size - p.position.y - 1;
p.position.y = size-1;
p.direction = Direction::Down;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(2, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size - p.position.x - 1;
p.position.y = size-1;
p.direction = Direction::Up;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = 0;
return p;
}))));
}
{
let (x, y) = (1, 1);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.y = p.position.x;
p.position.x = 0;
p.direction = Direction::Right;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(0, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(2, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.x - 1;
p.position.x = 0;
p.direction = Direction::Right;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(2, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = 0;
return p;
}))));
}
{
let (x, y) = (2, 1);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(2, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.y = 0;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(3, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size - p.position.y - 1;
p.position.y = 0;
p.direction = Direction::Down;
return p;
}))));
}
{
let (x, y) = (2, 2);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(2, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size - p.position.y - 1;
p.position.y = size-1;
p.direction = Direction::Up;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(0, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size - p.position.x - 1;
p.position.y = size-1;
p.direction = Direction::Up;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(3, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = 0;
return p;
}))));
}
{
let (x, y) = (3, 2);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(2, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.x - 1;
p.position.x = size-1;
p.direction = Direction::Left;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(2, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(0, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.x - 1;
p.position.x = 0;
p.direction = Direction::Left;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.y - 1;
p.position.x = size-1;
p.direction = Direction::Left;
return p;
}))));
}
}
// Setup the connection to the neighbours for the actual input
// @TODO Automatically construct this instead of manually figuring out where every edge leads
// For now this is fine as appearently all inputs have the same shape, so this should be good
// enough to solve every input, but it is not pretty at all...
fn fill_neighbours_part2_solution(&mut self) {
let size = self.size;
{
let (x, y) = (1, 0);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(0, 3), Rc::new(Box::new(move |mut p: Player| {
p.position.y = p.position.x;
p.position.x = 0;
p.direction = Direction::Right;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(0, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.y - 1;
p.position.x = 0;
p.direction = Direction::Right;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = 0;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.x = 0;
return p;
}))));
}
{
let (x, y) = (2, 0);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(0, 3), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(1, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = p.position.x;
p.position.x = size-1;
p.direction = Direction::Left;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(1, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.y - 1;
p.position.x = size-1;
p.direction = Direction::Left;
return p;
}))));
}
{
let (x, y) = (1, 1);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(1, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(0, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = p.position.y;
p.position.y = 0;
p.direction = Direction::Down;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(1, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.y = 0;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.x = p.position.y;
p.position.y = size-1;
p.direction = Direction::Up;
return p;
}))));
}
{
let (x, y) = (0, 2);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = p.position.x;
p.position.x = 0;
p.direction = Direction::Right;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(1, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.x - 1;
p.position.x = 0;
p.direction = Direction::Right;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(0, 3), Rc::new(Box::new(move |mut p: Player| {
p.position.y = 0;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(1, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = 0;
return p;
}))));
}
{
let (x, y) = (1, 2);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(1, 1), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(0, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(0, 3), Rc::new(Box::new(move |mut p: Player| {
p.position.y = p.position.x;
p.position.x = size-1;
p.direction = Direction::Left;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size - p.position.y - 1;
p.position.x = size-1;
p.direction = Direction::Left;
return p;
}))));
}
{
let (x, y) = (0, 3);
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Up)] = Some((Vec2::new(0, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.y = size-1;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Left)] = Some((Vec2::new(1, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.x = p.position.y;
p.position.y = 0;
p.direction = Direction::Down;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Down)] = Some((Vec2::new(2, 0), Rc::new(Box::new(move |mut p: Player| {
p.position.y = 0;
return p;
}))));
self.planes[y][x].as_mut().unwrap().neighbours[usize::from(&Direction::Right)] = Some((Vec2::new(1, 2), Rc::new(Box::new(move |mut p: Player| {
p.position.x = p.position.y;
p.position.y = size-1;
p.direction = Direction::Up;
return p;
}))));
} }
} }
} }
@ -428,8 +811,13 @@ impl aoc::Solver for Day {
let size = if is_test(input) { 4 } else { 50 }; let size = if is_test(input) { 4 } else { 50 };
let mut map = Map::new(map, size); let mut map = Map::new(map, size);
map.fill_neighbours_part2(); if is_test(input) {
map.fill_neighbours_part2_test();
} else {
map.fill_neighbours_part2_solution();
}
// Create the movement instructions and execute them
let moves = parse_movement(movement); let moves = parse_movement(movement);
map.movement(moves); map.movement(moves);