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

Day 2

day02.livemd

Day 2

Mix.install([
  {:kino, "~> 0.11.3"}
])

Data

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

Solutions

Day 2: Cube Conundrum

For example, the record of a few games might look like this:

Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green

If you add up the IDs of the games that would have been possible, you get 8.

Part Two

Adding up these five powers produces the sum 2286.

input = Kino.Input.read(input)

defmodule Advent2023.Day01 do
  @limit_p1 %{red: 12, green: 13, blue: 14}

  def p1(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.map(&parse_line/1)
    |> Enum.filter(&validate_rounds/1)
    |> Enum.map(fn [game_number, _rounds] -> game_number end)
    |> Enum.sum()
  end

  def parse_line(line) do
    pattern = ~r/^Game (\d+): (.+)/
    [_, game_number, all_rounds] = Regex.run(pattern, line)
    [String.to_integer(game_number), parse_rounds(all_rounds)]
  end

  def parse_rounds(rounds) do
    rounds
    |> String.split(";", trim: true)
    |> Enum.map(&parse_round/1)
  end

  def parse_round(rounds) do
    pattern = ~r/(\d+) (red|green|blue)/

    Regex.scan(pattern, rounds)
    |> Enum.map(fn [_, count, color] -> {String.to_atom(color), String.to_integer(count)} end)
    |> Enum.into(%{})
  end

  def validate_rounds([_game_number, rounds]) do
    Enum.all?(rounds, &validate_round/1)
  end

  def validate_round(round) do
    Map.keys(round)
    |> Enum.all?(fn color -> round[color] <= @limit_p1[color] end)
  end

  def p2(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.map(&amp;parse_line/1)
    |> Enum.map(&amp;maximum_cube_set/1)
    |> Enum.sum()
  end

  def maximum_cube_set([_game_number, rounds]) do
    rounds
    |> Enum.reduce(%{}, fn round, acc ->
      Map.merge(acc, round, fn _, v1, v2 -> Enum.max([v1, v2]) end)
    end)
    |> Map.values()
    |> Enum.reduce(1, &amp;Kernel.*(&amp;1, &amp;2))
  end
end

Advent2023.Day01.p1(input)
|> IO.puts()

Advent2023.Day01.p2(input)
|> IO.puts()