antoine-duchenet
Advent of Code 2024 - Day 11
Everything went smoothly today.
Nothing to change to solve part 2 because I already used memoization for part 1 (it looked like an AoC exercise where it would be useful
).
Here are the main parts :
defp blink([_], 0), do: 1
defp blink([0], steps), do: blink([1], steps - 1)
defp blink([h], steps) do
Performance.memoize({h, steps}, fn ->
case should_split?(h) do
{true, split_params} -> split_params |> split() |> blink(steps - 1)
_ -> blink([h * 2024], steps - 1)
end
end)
end
defp blink([h | tail], steps) do
blink([h], steps) + blink(tail, steps)
end
Part 2 takes ~100ms ~70ms to run.
A virtual part 3 with 1000 blinks instead of 75 takes “only” ~5475ms to run.
Most Liked
billylanchantin
PSA: If you’re using Elixir 1.18, now there’s:
No more Enum.reduce(enum, 0, &(&1 + &2)) ![]()
6
mexicat
Once I had coffee and realized that order doesn’t matter I just used plain old Maps:
Part 1 runs in ~700μs, part 2 runs in ~40ms.
4
sevenseacat
Author of Ash Framework
Oh yes, and even when stones are replaced, they always stay in the same order! Makes you think that order is important
3
Flo0807
My solution using ETS. It takes 56.94 ms for Part 2 with a clean cache.
defmodule PlutonianPebbles do
def init_cache do
if :ets.whereis(:stones_cache) != :undefined do
:ets.delete(:stones_cache)
end
:ets.new(:stones_cache, [:set, :public, :named_table])
end
def blink_stone(0), do: 1
def blink_stone(stone) do
digits = Integer.digits(stone)
len = length(digits)
if rem(len, 2) == 0 do
mid = div(len, 2)
first = Enum.take(digits, mid) |> Integer.undigits()
second = Enum.drop(digits, mid) |> Integer.undigits()
{first, second}
else
2024 * stone
end
end
def count_stones(stones, depth) when is_list(stones) do
stones
|> Enum.map(&count_stones(&1, depth))
|> Enum.sum()
end
def count_stones(stone, depth) do
cache_key = {stone, depth}
case :ets.lookup(:stones_cache, {stone, depth}) do
[{_key, result}] ->
result
[] ->
calculate_stones(stone, depth)
|> tap(fn result ->
:ets.insert(:stones_cache, {cache_key, result})
end)
end
end
defp calculate_stones({_first, _second}, 0), do: 2
defp calculate_stones(_stone, 0), do: 1
defp calculate_stones(stone, depth) do
case blink_stone(stone) do
{first, second} ->
count_stones(first, depth - 1) + count_stones(second, depth - 1)
stone ->
count_stones(stone, depth - 1)
end
end
end
nums = String.split(puzzle_input) |> Enum.map(&String.to_integer(&1))
PlutonianPebbles.init_cache()
# Part 1
PlutonianPebbles.count_stones(nums, 25)
# Part 2
PlutonianPebbles.count_stones(nums, 75)
2
Aetherus
I was stupid. I don’t need a graph.
blink = fn
0 ->
[1]
n ->
len = floor(:math.log10(n)) + 1
if Bitwise.band(len, 1) == 1 do
[n * 2024]
else
d = 10 ** Bitwise.bsr(len, 1)
[div(n, d), rem(n, d)]
end
end
############################
puzzle_input
|> String.split()
|> Enum.map(&String.to_integer/1)
|> Enum.frequencies()
|> Stream.iterate(fn freqs ->
for {num, freq} <- freqs, num2 <- blink.(num), reduce: %{} do
freqs2 -> Map.update(freqs2, num2, freq, & &1 + freq)
end
end)
|> Enum.at(75)
|> Map.values()
|> Enum.sum()
2
Popular in Challenges
Note by the Moderators: This topic is to talk about Day 5 of the Advent of Code.
For general discussion about the Advent of Code 2018 an...
New
Note: This topic is to talk about Day 9 of the Advent of Code.
For general discussion about the Advent of Code 2018 and links to topics ...
New
This topic is about Day 3 of the Advent of Code 2020 .
Thanks to @egze, we have a private leaderboard:
https://adventofcode.com/2020/le...
New
Continuation of Advent of Code 2022:christmas_tree:, Day 1:
Day 2!
Leaderboard:
New
This topic is about Day 9 of the Advent of Code 2021 .
We have a private leaderboard (shared with users of Erlang Forums):
https://adve...
New
Note: This topic is to talk about Day 18 of the Advent of Code 2019.
There is a private leaderboard for elixirforum members. You can joi...
New
Probably not the most efficient implementation, because part 1 took >1 ms and part 2 >4ms, but the code was simple enough.
def p...
New
Hi, there :wave:
Today, I felt it was way more challenging! I went through part2 thanks to Agent based memoization (without memoization ...
New
I spent 3 hours struggling in part 2, until I noticed a very basic mistake :joy:
Here’s my code:
By the way, the starting position in...
New
Since I started using Elixir, I have benefited greatly from being able to study various open-source projects. The codebase of LiveBook, i...
New
Other popular topics
Update:
How to use the Blogs & Podcasts section
You can post links to your blog posts or podcasts either in one of the Official Blog...
New
After calling mix ecto.create I get this error:
17:00:32.162 [error] GenServer #PID<0.412.0> terminating
** (Postgrex.Error) FATAL...
New
Phoenix 1.4.0 released
Phoenix 1.4 is out! This release ships with exciting new features, most notably
with HTTP2 support, improved deve...
New
Hello all!
I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
Good day to you all.
I have been struggling to get a query involving like and ilike to work.
Can anyone assist me on this, please?
pro...
New
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
Hey,
Just curious what are the main benefits of Elixir compared to Clojure?
When is Elixir more useful than Clojure and vice versa?
Th...
New
Hello, I have map which I want to convert it to string like this:
the map:
%{last_name: "tavakkoli", name: "shahryar"}
the string I ne...
New
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New








