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

AoC 2023 - Day 2

2023/day02.livemd

AoC 2023 - Day 2

Mix.install([:kino])

Section

input = Kino.Input.textarea("enter your input")
defmodule AoC.Day2 do
  def parse_line(line) do
    line_regex = ~r/Game\s(\d+):\s(.*)/
    [[_, id, result]] = Regex.scan(line_regex, line)

    maxs =
      result
      |> String.split(";", trim: true)
      |> Enum.flat_map(fn set ->
        set
        |> String.split(",", trim: true)
        |> Enum.map(&parse_set(&1))
      end)
      |> Enum.reduce(%{:green => 0, :red => 0, :blue => 0}, fn val, acc ->
        {color, count} = val

        if count > acc[color] do
          Map.put(acc, color, count)
        else
          acc
        end
      end)

    {num, ""} = Integer.parse(id)
    {num, maxs}
  end

  def filter_line_part_1({_id, local_max}, maximums) do
    cond do
      local_max[:green] > maximums[:green] ->
        false

      local_max[:red] > maximums[:red] ->
        false

      local_max[:blue] > maximums[:blue] ->
        false

      true ->
        true
    end
  end

  defp parse_set(set) do
    set_regex = ~r/(\d+)\s(.*)/
    [[_, count, color]] = Regex.scan(set_regex, set)
    {num, ""} = Integer.parse(count)
    atom_color = String.to_atom(color)
    {atom_color, num}
  end
end

Part 1

maximums = %{
  red: 12,
  green: 13,
  blue: 14
}

input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&AoC.Day2.parse_line(&1))
|> Enum.filter(&AoC.Day2.filter_line_part_1(&1, maximums))
|> Enum.map(fn {id, _} -> id end)
|> Enum.sum()

Part 2

input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&AoC.Day2.parse_line(&1))
|> Enum.map(fn {_, %{green: green, red: red, blue: blue}} ->
  green * red * blue
end)
|> Enum.sum()