bjorng

bjorng

Erlang Core Team

Advent of Code 2023 - Day 25

I came up with a solution myself, but it is not fast.

My first brute-force solution simply tried removing all combinations of three edges and check if the resulting graph had two components. That algorithm had quartic complexity and would probably have taken weeks to finish.

My second solution was to remove all combinations of two edges. The third edge to remove can then be found in linear time with a simple algorithm based on DFS. That algorithm has “only” cubic complexity, which allowed it to finish in “only” one hour and twenty minutes.

https://github.com/bjorng/advent-of-code-2023/blob/main/day25/lib/day25.ex

Most Liked

midouest

midouest

I implemented Karger’s algorithm for finding the min-cut and then applied it repeatedly until the cut size was 3:

Part 1
defmodule Part1 do
  def parse(input) do
    for line <- String.split(input, "\n", trim: true),
        reduce: %{} do
      acc ->
        [a | rest] = String.split(line, [":", " "], trim: true)

        for b <- rest,
            reduce: acc do
          acc ->
            acc
            |> Map.update(a, MapSet.new([b]), &MapSet.put(&1, b))
            |> Map.update(b, MapSet.new([a]), &MapSet.put(&1, a))
        end
    end
  end

  def group_product(graph) do
    Map.keys(graph)
    |> Enum.map(&String.length/1)
    |> Enum.map(&div(&1, 3))
    |> Enum.product()
  end

  def cut_size(g1, g0) do
    [as, bs] =
      for key <- Map.keys(g1) do
        key
        |> String.to_charlist()
        |> Enum.chunk_every(3)
        |> Enum.map(&to_string/1)
      end

    bs = MapSet.new(bs)

    for a <- as,
        _ <- MapSet.intersection(g0[a], bs),
        reduce: 0 do
      acc -> acc + 1
    end
  end

  def contract(graph) when map_size(graph) == 2, do: graph

  def contract(graph) do
    {a, ea} = Enum.random(graph)
    b = Enum.random(ea)
    eb = graph[b]

    ab = a <> b

    ea = MapSet.delete(ea, b)
    eb = MapSet.delete(eb, a)

    eab = MapSet.union(ea, eb)

    graph =
      Enum.reduce(ea, graph, fn c, graph ->
        Map.update!(graph, c, fn ec ->
          ec
          |> MapSet.delete(a)
          |> MapSet.put(ab)
        end)
      end)

    graph =
      Enum.reduce(eb, graph, fn c, graph ->
        Map.update!(graph, c, fn ec ->
          ec
          |> MapSet.delete(b)
          |> MapSet.put(ab)
        end)
      end)

    graph =
      graph
      |> Map.delete(a)
      |> Map.delete(b)
      |> Map.put(ab, eab)

    contract(graph)
  end
end

g0 = Part1.parse(input)

Stream.repeatedly(fn -> Part1.contract(g0) end)
|> Enum.find(fn g1 -> Part1.cut_size(g1, g0) == 3 end)
|> Part1.group_product()

Now I just need to finish the other puzzles so that I can complete part 2!

Where Next?

Popular in Challenges Top

adamu
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 ...
New
Aetherus
Hello, guys. I’m back again, but only for the weekends, maybe. This topic is about Day 13 of the Advent of Code 2020 . Thanks to @egze,...
New
rugyoga
Not the prettiest but it works https://github.com/rugyoga/aoc2023/blob/main/lib/2024/9.ex
New
bjorng
This topic is about Day 6 of the Advent of Code 2021. We have a private leaderboard (shared with users of Erlang Forums ): https://adve...
New
bjorng
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
groovyda
Today’s challenge for me was about using reduce: defmodule Prob5 do def move([[h1 | rest] = _list1, list2]) do [rest, [h1 | list2]...
New
liamcmitchell
A frustrating one for me. I spent a long time trying to understand why some combinations resulted in fewer presses and struggled to keep ...
New
stevensonmt
Anyone else think the prompt for this challenge is contradictory? The rules for comparing packets include If both values are lists, c...
New
Aetherus
This topic is about Day 16 of the Advent of Code 2020 . Thanks to @egze, we have a private leaderboard: https://adventofcode.com/2020/l...
New
christhekeele
Thought I’d kick today’s thread off! Parsing Enum rocks, so most of my code was actually in parsing input. ▶ Preprocessing input Part 1...
New

Other popular topics Top

New
albydarned
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
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement