vkryukov
Nice little problem. The right data structure is half the solution!
defmodule Y2025.Day08 do
def pairs(enum) do
l = enum |> Enum.with_index()
for {a, i} <- l, {b, j} <- l, i < j, do: {a, b}
end
def norm([x1, y1, z1], [x2, y2, z2]),
do: (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2)
defmodule Circuits do
def new(enum), do: Enum.into(enum, %{}, fn x -> {x, MapSet.new([x])} end)
def fuze(circuits, c1, c2) do
s1 = circuits[c1]
s2 = circuits[c2]
if s1 == s2 do
circuits
else
s = MapSet.union(s1, s2)
s |> Enum.reduce(circuits, fn el, circuits -> Map.put(circuits, el, s) end)
end
end
def product_top_3_sizes(circuits) do
circuits
|> Enum.uniq_by(&elem(&1, 1))
|> Enum.map(fn {_, v} -> MapSet.size(v) end)
|> Enum.sort(:desc)
|> Enum.take(3)
|> Enum.product()
end
end
def parse(s), do: s |> String.split("\n") |> Enum.map(&parse_line/1) |> Circuits.new()
def parse_line(s), do: s |> String.trim() |> String.split(",") |> Enum.map(&String.to_integer/1)
def fuze_while(circuits, start, fun) do
Map.keys(circuits)
|> pairs()
|> Enum.map(fn {a, b} -> {a, b, norm(a, b)} end)
|> Enum.sort_by(&elem(&1, 2))
|> Enum.reduce_while(start, fun)
end
def part1(s, n) do
circuits = parse(s)
fuze_while(circuits, {circuits, 0}, fn {c1, c2, _}, {circuits, count} ->
if count == n do
{:halt, circuits |> Circuits.product_top_3_sizes()}
else
{:cont, {Circuits.fuze(circuits, c1, c2), count + 1}}
end
end)
end
def part2(s) do
circuits = parse(s)
n = map_size(circuits)
fuze_while(circuits, circuits, fn {c1, c2, _}, circuits ->
if MapSet.union(circuits[c1], circuits[c2]) |> MapSet.size() == n do
{:halt, List.first(c1) * List.first(c2)}
else
{:cont, Circuits.fuze(circuits, c1, c2)}
end
end)
end
end
Trending in Challenges
Other Trending Topics
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
bjorng
I implemented a union-find algorithm to group junction boxes into circuits. The combined runtime for both part is 0.4 seconds on my computer.
lkuty
hauleth
Parse
Setup
Part 1
Part 2
Not the most performant implementation (each part runs in about 3s on my machine), but it is good enough. It probably could use some clever algorithms, but I didn’t want to spend too much time on it.
EDIT: I have improved squashing of sets to make it run in 30ms each (sans creating and sorting list of pairs).
Aetherus
My code is almost the same as yours, except one difference: I added an ID (generated with
make_ref()) to eachMapSet.t()so that I don’t have to compare two whole sets, instead I just compare their ID.lud
My solution takes 680ms, which is slow, I compute all distances upfront like many of you
I think I could optimize by keeping a double index position=>group and group=>positions to speed up the circuit merging, but I’m too lazy today
hauleth
If you copy set instead of constructing it 2 separately, then
==will be as fast for maps as it is for refs. So in this case:Will be immediate.
Aetherus
Is it also O(1) when comparing a and b using
==whena != b?hauleth
AFAIK - no, but I think that in most cases it will be negligible. I would need to check how exactly map equality is implemented.
rvnash
Fun!
Did the following:
Enum.count(circuits) == 1do statement. I don’t need the count, just need to know if it is 1 or not. Is there a faster way to see if an Enum has 1 element?Processing time is about 250ms for part1 and part2.
sevenseacat
https://github.com/sevenseacat/advent_of_code/blob/main/lib/y2025/day08.ex
My initial implementation was really silly - find the closest pair each time, and then update a list of MapSets - before I was like ohhhhhh this is a graph problem isn’t it?
So I precomputed all of the distances between each pair of junction boxes, started mucking around with graphs - looking at my solution now I think I over-optimized it and it works by chance (just because all nodes are connected to something, doesn’t mean they’re all in one big circuit…) but hey I’ll take it!
(The previous version I had is probably more accurate - on each join, checking if
length(Graph.components(graph)) == 1)