Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Advent of Code 2024 - Day 19

2024/day-19.livemd

Advent of Code 2024 - Day 19

Mix.install([
  {:kino, github: "livebook-dev/kino"},
  {:memoize, "~> 1.4"},
])

kino_input = Kino.Input.textarea("Please paste your input file: ")

Part 1

input = Kino.Input.read(kino_input)

defmodule Combinations do
  use Memoize
  defmemo can_construct?("", _patterns), do: true

  defmemo can_construct?(design, patterns) do
    patterns
    |> Enum.any?(fn pattern ->
      case String.starts_with?(design, pattern) do
        true ->
          rest = String.replace_prefix(design, pattern, "")
          can_construct?(rest, patterns)

        false ->
          false
      end
    end)
  end
end


input
|> String.split("\n\n")
|> then(fn [patterns_str, designs_str] ->
  patterns = patterns_str |> String.split(", ")
  designs = designs_str |> String.split("\n", trim: true)

  Enum.map(designs, fn design ->
    {design, Combinations.can_construct?(design, patterns)}
  end)
end)
|> Enum.count(fn {_design, result} -> result end)

Part 2

input = Kino.Input.read(kino_input)

defmodule CombinationsPart2 do
  use Memoize
  defmemo count_ways("", _patterns), do: 1

  defmemo count_ways(design, patterns) do
    patterns
    |> Enum.reduce(0, fn pattern, total ->
      if String.starts_with?(design, pattern) do
        rest = String.replace_prefix(design, pattern, "")
        total + count_ways(rest, patterns)
      else
        total
      end
    end)
  end
end


input
|> String.split("\n\n")
|> then(fn [patterns_str, designs_str] ->
  patterns = patterns_str |> String.split(", ")
  designs = designs_str |> String.split("\n", trim: true)

  Enum.map(designs, fn design ->
    {design, CombinationsPart2.count_ways(design, patterns)}
  end)
end)
|> Enum.map(fn {_design, number_of_ways} -> number_of_ways end)
|> Enum.sum()