AOC 23 - Day 10 - Pipe Maze
Thanks to the hang glider, we are now on the floating metal island. Everything is made of metal, but you saw something metallic jumping in a network of pipes. To know what it is, we'll need to have a better look by anticipating his next exit !
Part 1
Rules
The part one is a 2d grid, with pipes having different shapes, connecting different directions:
| is a vertical pipe connecting north and south.
- is a horizontal pipe connecting east and west.
L is a 90-degree bend connecting north and east.
J is a 90-degree bend connecting north and west.
7 is a 90-degree bend connecting south and west.
F is a 90-degree bend connecting south and east.
. is ground; there is no pipe in this tile.
S is the starting position of the animal; there is a pipe on this tile, but your sketch doesn't show what shape the pipe has.
The input looks like this:
.F7.
.FJ|.
SJ.L7
|F--J
LJ...
And each input contains a loop, in which the starting position S
is part of.
The first part of today is to find How many steps along the loop does it take to get from the starting position to the point farthest from the starting position.
For example with the previous input, the distances looks like this:
..45.
.236.
01.78
14567
23...
And the result would be 8
.
Code
To handle today's problem, the parsing and data structure will be simple: just convert the input to a 2d array, with the connected tiles as values. We just need to handle the special tile S
, and figure it's connections.
:
:
yield
yield
yield
yield
=
=
= None
=
=
# Since we ignored the value `S`, we need to infer it's connections
# by looking which nodes are pointing to `S`
return ,
"""Return the connections for a given value according to the following descriptions:
| is a vertical pipe connecting north and south.
- is a horizontal pipe connecting east and west.
L is a 90-degree bend connecting north and east.
J is a 90-degree bend connecting north and west.
7 is a 90-degree bend connecting south and west.
F is a 90-degree bend connecting south and east.
Returns an empty array if the value is not part of these values.
"""
# Each value is the delta in form [(y, x), (y, x)]
=
return
=
, =
=
return
With these data, we need to find the distance which is the furthest from the starting point.
For this, we can use a classic BFS: we start from one side of S
, and we are looking to join the other side of S
.
The trick is to add S
in the visited
list at the beginning, to break the link between the start and end node:
=
# We are looking to go from one side to the other side of the loop
= ,
, # We add `s_point` to `visited` as well,
# to break the link between `left_side` and `right_side`
=
=
=
=
return
=
After that, we need to implement the function to have the len between 2 points:
=
=
=
return
With these functions, the part 1 can be simply solved by computing the path, get it's len, and return it's len divided by 2:
=
, =
, =
return // 2
And the part one is done !
Part 2
Rules
For the part 2, we need to find the number of points in the area enclosed by the loop.
For example, with the input
..........
.S------7.
.|F----7|.
.||....||.
.||....||.
.|L-7F-J|.
.|..||..|.
.L--JL--J.
..........
There is 4 tiles enclosed by the loop, which are represented by the I
:
..........
.S------7.
.|F----7|.
.||OOOO||.
.||OOOO||.
.|L-7F-J|.
.|II||II|.
.L--JL--J.
..........
The tiles O
are still counted as outside the loop, since they can squeeze between the pipes at the bottom.
Any tile that isn't part of the main loop can count as being enclosed by the loop.
Code
Sadly I didn't had time to finish this part. I'll come back later and update this post once it's done.
I though about a rather long, and not very efficient solution:
- discard all the tiles which are not part of the main loop
- Space all tiles by one empty tile. For example,
F-7
|.|
L-J
Would become
F.-.7
.....
|...|
.....
L.-.J
- Link all the new empty tiles if they are between 2 pipes which were previously connected to each other.
F.-.7
.....
|...|
.....
L.-.J
will become
F---7
|...|
|...|
|...|
L---J
- Detect the outside of the map and replace the empty tiles with a flood-fill algorithm.
.......
.F---7.
.|...|.
.|...|.
.|...|.
.L---J.
.......
would become
#######
#F---7#
#|...|#
#|...|#
#|...|#
#L---J#
#######
- Once it's done, we just have to count the empty remaining tiles.
It should work because by expanding the grid and linking only the previously connected pipe, we are adding some gaps between 2 adjacent pipes which are not connected. The flood-fill algorithm is now possible.
All the code is available on github