adamu
Advent of Code 2024 - Day 14
I said I was on a break, but I took a sneak peak and it looked fun so…
Part 1 completes in half a millisecond with a single pass of the robots. Integer.mod/2 to the rescue.
I was expecting part 2 to to be “and now 1 billion seconds??” but that took me by surprise. Not enough time to figure it out but I’m guessing looking for the centre y axis being full of robots will find it.
Part 1 solution:
def part1({robots, size_x, size_y}) do
mid_x = div(size_x, 2)
mid_y = div(size_y, 2)
robots
|> Enum.reduce({0, 0, 0, 0}, fn [px, py, vx, vy], {a, b, c, d} ->
x = Integer.mod(px + vx * 100, size_x)
y = Integer.mod(py + vy * 100, size_y)
case {x, y} do
{x, y} when x < mid_x and y < mid_y -> {a + 1, b, c, d}
{x, y} when x < mid_x and y > mid_y -> {a, b + 1, c, d}
{x, y} when x > mid_x and y < mid_y -> {a, b, c + 1, d}
{x, y} when x > mid_x and y > mid_y -> {a, b, c, d + 1}
{x, y} when x == mid_x or y == mid_y -> {a, b, c, d}
end
end)
|> Tuple.product()
end
https://git.adamu.jp/adam/AdventOfCode/src/branch/main/2024/day14.exs
Most Liked
bossek
Finding minimal variance of positions worked for me in part 2. For each second in range 0..(101 * 103) I’ve calculated variance of robots’ positions:
defp variance(positions) do
{xs, ys} = Enum.unzip(positions)
xl = length(xs)
yl = length(ys)
xmean = Enum.sum(xs) / xl
ymean = Enum.sum(ys) / yl
xvar = Enum.sum(Enum.map(xs, fn x -> (x - xmean) ** 2 end)) / xl
yvar = Enum.sum(Enum.map(ys, fn y -> (y - ymean) ** 2 end)) / yl
(xvar + yvar) / 2
end
The second with minimal variance was the solution.
bjorng
This was a fun day.
I initially solved part 2 by printing out a map with the robots after each second. I then did some creative grepping to find the Christmas tree. Knowing what the Christmas tree looks like, I could create a unique pattern to use when searching for the Christmas tree programmatically.
The combined running time for both parts is 2.3 seconds.
https://github.com/bjorng/advent-of-code/blob/main/2024/day14/lib/day14.ex
lud
Thank you guys. I found it by searching contiguous cells and it worked :). I’m not sure if I want to implement the pattern search because you need to know the tree shape already.
Edit: Alright, did it anyway, looking for the tip of the tree is 400ms
Enum.reduce_while(1..10000, nil, fn sec, _ ->
positions = Enum.map(robots, &simulate(&1, room_dimensions, sec))
map = Map.new(positions, &{&1, true})
if Enum.all?([{43, 57}, {42, 58}, {43, 58}, {44, 58}], &Map.has_key?(map, &1)) do
{:halt, sec}
else
{:cont, nil}
end
end)
end
Also it was very slow because of my modulo function:
defp mod(0, _), do: 0
defp mod(n, m) when n < 0, do: mod(m + n, m)
defp mod(n, m), do: rem(n, m)
Looking at the implementation I can see why
But today I learnt Integer.mod/2 exists!
Edit2: since the slow thing was the modulo, the map is actually slower. this is around 140ms:
Enum.reduce_while(1..10000, nil, fn sec, _ ->
positions = Enum.map(robots, &simulate(&1, room_dimensions, sec))
if Enum.all?([{43, 57}, {42, 58}, {43, 58}, {44, 58}], & &1 in positions) do
{:halt, sec}
else
{:cont, nil}
end
end)
Edit this will not work for any input if not everyone has the tree in the same position. I don’t know if it is the case.
Popular in Challenges
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









