Day 17 Parts 1 and 2
This commit is contained in:
parent
d607504faf
commit
e6991afe00
5 changed files with 177 additions and 1 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
My (attempted) solutions to [Advent of Code 2020](https://adventofcode.com/2020) in Elixir.
|
||||
|
||||
<img width="978" alt="image" src="https://user-images.githubusercontent.com/498229/102717151-cdc3a700-4323-11eb-930e-613465f503d1.png">
|
||||
<img width="978" alt="image" src="https://user-images.githubusercontent.com/498229/102721772-43d60700-4340-11eb-9ccc-baa6479559f8.png">
|
||||
|
||||
## Strategy
|
||||
|
||||
|
|
44
day17/README
Normal file
44
day17/README
Normal file
|
@ -0,0 +1,44 @@
|
|||
Day 17 Notes
|
||||
|
||||
+--------+
|
||||
| Part 1 |
|
||||
+--------+
|
||||
|
||||
$ elixir day17part1.exs
|
||||
362
|
||||
|
||||
Thoughts:
|
||||
|
||||
The answer is not pretty, but it works.
|
||||
|
||||
Rather than iterate through the entire coordinate plane, which would require keeping track of where
|
||||
the current extremities are, I decided to only keep the set of active cubes around. Then for each
|
||||
iteration, check all the active cube's neighbours.
|
||||
|
||||
In addition to counting the neighbours for the active cube, keep track of the inactive neighbours,
|
||||
then check *their* neighbours too to see if they should become active.
|
||||
|
||||
+--------+
|
||||
| Part 2 |
|
||||
+--------+
|
||||
|
||||
$ elixir day17part2.exs
|
||||
1980
|
||||
|
||||
Thoughts:
|
||||
|
||||
In Part 1 I was half expecting a high iteration count for part 2, hence why I avoided iterating the
|
||||
entire plane. Instead, adding a 4th dimension was a two-line change :-)
|
||||
|
||||
+------------------+
|
||||
| Overall Thoughts |
|
||||
+------------------+
|
||||
|
||||
Nice to have a quick Part 2 solve after day 18 which took me ages. I probably dug myself into
|
||||
a hole on day 18 though and should have took a step back and tried with a clearer mind.
|
||||
|
||||
I spent quite a while getting distracted by the examples, because they present a sliding plane.
|
||||
Turns out I had actually written the correct implementation, I just struggled to translate my
|
||||
coordinates to the graphical examples. Running the script produced the correct answer though, but
|
||||
I cross-referenced it with one of the confusing examples, just in case it wasn't pure luck. I'm
|
||||
glad I was able to solve Part 2 without reading all the dreaded 4D examples there too!
|
59
day17/day17part1.exs
Normal file
59
day17/day17part1.exs
Normal file
|
@ -0,0 +1,59 @@
|
|||
defmodule Day17Part1 do
|
||||
def run do
|
||||
File.read!("input")
|
||||
|> String.split("\n", trim: true)
|
||||
|> parse_input()
|
||||
|> boot(6)
|
||||
|> Enum.count()
|
||||
|> IO.puts()
|
||||
end
|
||||
|
||||
def parse_input(input) do
|
||||
{_y, cubes} =
|
||||
Enum.reduce(input, {0, MapSet.new()}, fn row, {y, cubes} ->
|
||||
{_x, cubes} =
|
||||
Enum.reduce(String.graphemes(row), {0, cubes}, fn
|
||||
".", {x, cubes} -> {x + 1, cubes}
|
||||
"#", {x, cubes} -> {x + 1, MapSet.put(cubes, {x, y, 0})}
|
||||
end)
|
||||
|
||||
{y + 1, cubes}
|
||||
end)
|
||||
|
||||
cubes
|
||||
end
|
||||
|
||||
def boot(cubes, 0), do: cubes
|
||||
def boot(cubes, count), do: boot(cycle(cubes), count - 1)
|
||||
|
||||
def cycle(cubes) do
|
||||
{next_cubes, inactives} =
|
||||
Enum.reduce(cubes, {MapSet.new(), MapSet.new()}, fn cube, {next_cubes, inactives} ->
|
||||
{active_count, inactives} =
|
||||
Enum.reduce(neighbours(cube), {0, inactives}, fn neighbour, {active_count, inactives} ->
|
||||
if MapSet.member?(cubes, neighbour) do
|
||||
{active_count + 1, inactives}
|
||||
else
|
||||
{active_count, MapSet.put(inactives, neighbour)}
|
||||
end
|
||||
end)
|
||||
|
||||
next_cubes = if active_count in 2..3, do: MapSet.put(next_cubes, cube), else: next_cubes
|
||||
{next_cubes, inactives}
|
||||
end)
|
||||
|
||||
Enum.reduce(inactives, next_cubes, fn inactive, next_cubes ->
|
||||
active_neighbours =
|
||||
inactive |> neighbours() |> MapSet.new() |> MapSet.intersection(cubes) |> Enum.count()
|
||||
|
||||
if active_neighbours == 3, do: MapSet.put(next_cubes, inactive), else: next_cubes
|
||||
end)
|
||||
end
|
||||
|
||||
def neighbours({x, y, z} = me) do
|
||||
all = for x <- (x - 1)..(x + 1), y <- (y - 1)..(y + 1), z <- (z - 1)..(z + 1), do: {x, y, z}
|
||||
all -- [me]
|
||||
end
|
||||
end
|
||||
|
||||
Day17Part1.run()
|
65
day17/day17part2.exs
Normal file
65
day17/day17part2.exs
Normal file
|
@ -0,0 +1,65 @@
|
|||
defmodule Day17Part2 do
|
||||
def run do
|
||||
File.read!("input")
|
||||
|> String.split("\n", trim: true)
|
||||
|> parse_input()
|
||||
|> boot(6)
|
||||
|> Enum.count()
|
||||
|> IO.puts()
|
||||
end
|
||||
|
||||
def parse_input(input) do
|
||||
{_y, cubes} =
|
||||
Enum.reduce(input, {0, MapSet.new()}, fn row, {y, cubes} ->
|
||||
{_x, cubes} =
|
||||
Enum.reduce(String.graphemes(row), {0, cubes}, fn
|
||||
".", {x, cubes} -> {x + 1, cubes}
|
||||
"#", {x, cubes} -> {x + 1, MapSet.put(cubes, {x, y, 0, 0})}
|
||||
end)
|
||||
|
||||
{y + 1, cubes}
|
||||
end)
|
||||
|
||||
cubes
|
||||
end
|
||||
|
||||
def boot(cubes, 0), do: cubes
|
||||
def boot(cubes, count), do: boot(cycle(cubes), count - 1)
|
||||
|
||||
def cycle(cubes) do
|
||||
{next_cubes, inactives} =
|
||||
Enum.reduce(cubes, {MapSet.new(), MapSet.new()}, fn cube, {next_cubes, inactives} ->
|
||||
{active_count, inactives} =
|
||||
Enum.reduce(neighbours(cube), {0, inactives}, fn neighbour, {active_count, inactives} ->
|
||||
if MapSet.member?(cubes, neighbour) do
|
||||
{active_count + 1, inactives}
|
||||
else
|
||||
{active_count, MapSet.put(inactives, neighbour)}
|
||||
end
|
||||
end)
|
||||
|
||||
next_cubes = if active_count in 2..3, do: MapSet.put(next_cubes, cube), else: next_cubes
|
||||
{next_cubes, inactives}
|
||||
end)
|
||||
|
||||
Enum.reduce(inactives, next_cubes, fn inactive, next_cubes ->
|
||||
active_neighbours =
|
||||
inactive |> neighbours() |> MapSet.new() |> MapSet.intersection(cubes) |> Enum.count()
|
||||
|
||||
if active_neighbours == 3, do: MapSet.put(next_cubes, inactive), else: next_cubes
|
||||
end)
|
||||
end
|
||||
|
||||
def neighbours({x, y, z, w} = me) do
|
||||
all =
|
||||
for x <- (x - 1)..(x + 1),
|
||||
y <- (y - 1)..(y + 1),
|
||||
z <- (z - 1)..(z + 1),
|
||||
w <- (w - 1)..(w + 1),
|
||||
do: {x, y, z, w}
|
||||
|
||||
all -- [me]
|
||||
end
|
||||
end
|
||||
|
||||
Day17Part2.run()
|
8
day17/input
Normal file
8
day17/input
Normal file
|
@ -0,0 +1,8 @@
|
|||
...###.#
|
||||
#.#.##..
|
||||
.##.##..
|
||||
..##...#
|
||||
.###.##.
|
||||
.#..##..
|
||||
.....###
|
||||
.####..#
|
Loading…
Reference in a new issue