bjorng
Advent of Code 2020 - Day 17
This topic is about Day 17 of the Advent of Code 2020 .
Thanks to @egze, we have a private leaderboard:
https://adventofcode.com/2020/leaderboard/private/view/39276
The join code is:
39276-eeb74f9a
Most Liked
Hallski
They updated the text slightly after a while since a lot of people got confused by the example (me included). In short, the top left coordinate in the z0 layer is not the same in each iteration and moves around depending on where there are active satellites.
Hallski
Struggled for about an hour trying to make sense of the examples (and thought they meant the space wrapped around which created a real headache with a growing universe
).
I settled for storing the active satellites in a map, keyed on coordinates. Then I ran each iteration and checked all positions within my active state plus one in each direction.
Here is my solution.
Part 2 was simply extending part 1 with an extra dimension so only posted that.
@bjorng nice to use Stream.iterate() |> Enum.drop(6), also realised reading your code that I was a bit silly to filter my Map and use Enum.count since I also only store the active satellites in my map.
mruoss
Oh boy, I get it now! I was looking for something in the instructions, but it’s how the examples are displayed. The frame of view is moving!
I could have ignored the examples but it bothered me that my understanding after which I write the algorithm wouldn’t even comply with the example. Alright… let’s see where to find the motivation to solve this now… 
lud
Hi @faried
First thing is you can actually have multiple generators in your for construct, so you do not have to flatten:
def neighbors3({x, y, z}) do
for i <- -1..1,
j <- -1..1,
k <- -1..1 do
{x + i, y + j, z + k}
end
# we have to return the neighbors of a point, so we explicitly
# remove the point from the output
|> Enum.reject(fn {a, b, c} -> a == x and b == y and c == z end)
end
The best part is that you can still pull values out of a previous generated value, for example:
for values <- rows, value <- values, do: something(value)
Now, you need to use Enum.reject is simply because at one moment of the iteration, i is 0, j is 0 and k is also 0, so your expression {x + i, y + j, z + k} does not represent a neighbour but the central element itself.
That is why you have to “explicitly remove the point from the output” as you have said.
So you could filter-out the central point directly in the generator (in you case, that would be in the most inner for.
def neighbors3({x, y, z} = coords) do
for i <- -1..1,
j <- -1..1,
k <- -1..1,
n = {x + i, y + j, z + k},
n != coords do # <-- accept only when !=coords
n
end
end
What I did today, though, is directly count the numbers of neighbours, with a for + reduce loop. My map contains 0 for inactive cubes and 1 for active ones.
defp active_neighbours_count(map, {x, y, z} = coords) do
for nx <- (x - 1)..(x + 1),
ny <- (y - 1)..(y + 1),
nz <- (z - 1)..(z + 1),
{nx, ny, nz} != coords,
reduce: 0 do
acc ->
Map.get(map, {nx, ny, nz}, 0) + acc
end
end
faried
Thanks. I have used multiple generators with for in the past – I just didn’t think of it this time. I don’t work with Elixir on a day-to-day basis. One of the reasons I’m trying to do them all in Elixir this year is to learn from other solutions.
The Enum.reject I mentioned is in my cycle function, where I remove cubes that have no neighbors. That’s what fixes my off-by-one error. I had a lot of trouble figuring out why I need that.







