Sponsored by AppSignal
Would you like to see your link here? Contact us
Notesclub

Day 14

advent_of_code/2021/day-14.livemd

Day 14

Setup

Mix.install([
  {:kino, "~> 0.5.0"}
])
input = Kino.Input.textarea("Input")

Part 1

[template | lines] = input |> Kino.Input.read() |> String.split("\n", trim: true)

# Use null byte for the last pair as it never matches and we will discard later.
template = template |> String.to_charlist() |> Enum.chunk_every(2, 1, [0])
pairs = Map.new(lines, fn < ", o>> -> {[i1, i2], o} end)

result =
  Enum.reduce(1..10, template, fn _, polymer ->
    Enum.flat_map(polymer, fn [i1, i2] = pair ->
      case pairs do
        %{^pair => o} -> [[i1, o], [o, i2]]
        %{} -> [pair]
      end
    end)
  end)
  |> Enum.map(&amp;hd/1)

{{_, min}, {_, max}} = result |> Enum.frequencies() |> Enum.min_max_by(&amp;elem(&amp;1, 1))
max - min

Part 2

[template | lines] = input |> Kino.Input.read() |> String.split("\n", trim: true)

# Use null byte for the last pair as it never matches and we will discard later.
template =
  template
  |> String.to_charlist()
  |> Enum.chunk_every(2, 1, [0])
  |> Enum.frequencies()

pairs = Map.new(lines, fn < ", o>> -> {[i1, i2], o} end)

{{_, mins}, {_, maxes}} =
  1..40
  |> Enum.reduce(template, fn _, polymer ->
    Enum.reduce(polymer, %{}, fn {[i1, i2] = pair, count}, acc ->
      case pairs do
        %{^pair => o} ->
          acc
          |> Map.update([i1, o], count, &amp;(&amp;1 + count))
          |> Map.update([o, i2], count, &amp;(&amp;1 + count))

        %{} ->
          Map.put(acc, pair, count)
      end
    end)
  end)
  |> Enum.group_by(&amp;hd(elem(&amp;1, 0)), &amp;elem(&amp;1, 1))
  |> Enum.min_max_by(fn {_, counts} -> Enum.sum(counts) end)

Enum.sum(maxes) - Enum.sum(mins)

Other approaches