Powered by AppSignal & Oban Pro

Day 14

2021/day14.livemd

Day 14

[polymer_raw, subs] =
  File.read!("day14.txt")
  |> String.split("\n\n")

<> = polymer_raw

polymer =
  {first,
   polymer_raw
   |> String.to_charlist()
   |> Enum.chunk_every(2, 1, :discard)
   |> Enum.frequencies()}

subs =
  subs
  |> String.trim()
  |> String.split(["\n", " -> "])
  |> Enum.chunk_every(2)
  |> Map.new(fn [pair, <>] -> {String.to_charlist(pair), new} end)

defmodule Day14 do
  def expand({hd, polymer}, subs) do
    new =
      polymer
      |> Enum.reduce(%{}, fn {[a, b] = pair, count}, acc ->
        s = Map.fetch!(subs, pair)

        acc
        |> Map.update([a, s], count, &amp;(&amp;1 + count))
        |> Map.update([s, b], count, &amp;(&amp;1 + count))
      end)

    {hd, new}
  end

  def expand_naive(polymer, subs) do
    polymer
    |> to_charlist()
    |> Enum.chunk_every(2, 1, :discard)
    |> Enum.flat_map(fn [a, b] = pair ->
      [a, subs[pair], b]
    end)
    |> List.to_string()
  end

  def frequencies({hd, polymer}) do
    polymer
    |> Enum.reduce(%{hd => 1}, fn {[_, b], count}, acc ->
      Map.update(acc, b, count, &amp;(&amp;1 + count))
    end)
  end
end
{:module, Day14, <<70, 79, 82, 49, 0, 0, 13, ...>>, {:frequencies, 1}}

Task 1

{{_, min}, {_, max}} =
  1..10
  |> Enum.reduce(polymer, fn _, acc ->
    Day14.expand(acc, subs)
  end)
  |> Day14.frequencies()
  |> Enum.min_max_by(&amp;elem(&amp;1, 1))

# 2768
max - min
2768

Task 2

{{_, min}, {_, max}} =
  1..40
  |> Enum.reduce(polymer, fn _, acc ->
    Day14.expand(acc, subs)
  end)
  |> Day14.frequencies()
  |> Enum.min_max_by(&amp;elem(&amp;1, 1))

max - min
2914365137499