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

Advent 2023 - Day 2

day2.livemd

Advent 2023 - Day 2

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

Section

input = Kino.Input.textarea("Please paste your input file")
input =
  input
  |> Kino.Input.read()
  |> String.split("\n")
  |> Enum.map(fn line ->
    [game_id, rounds] = String.split(line, ": ")

    [_, game_id] = String.split(game_id, " ")
    {game_id, _} = Integer.parse(game_id)

    rounds =
      rounds
      |> String.split("; ")
      |> Enum.map(fn round ->
        round
        |> String.split(", ")
        |> Enum.map(fn pull ->
          [num, color] = String.split(pull, " ")
          num = num |> Integer.parse() |> elem(0)
          color = String.to_atom(color)
          {num, color}
        end)
      end)

    {game_id, rounds}
  end)
[
  {1, [[{3, :blue}, {4, :red}], [{1, :red}, {2, :green}, {6, :blue}], [{2, :green}]]},
  {2, [[{1, :blue}, {2, :green}], [{3, :green}, {4, :blue}, {1, :red}], [{1, :green}, {1, :blue}]]},
  {3,
   [
     [{8, :green}, {6, :blue}, {20, :red}],
     [{5, :blue}, {4, :red}, {13, :green}],
     [{5, :green}, {1, :red}]
   ]},
  {4,
   [
     [{1, :green}, {3, :red}, {6, :blue}],
     [{3, :green}, {6, :red}],
     [{3, :green}, {15, :blue}, {14, :red}]
   ]},
  {5, [[{6, :red}, {1, :blue}, {3, :green}], [{2, :blue}, {1, :red}, {2, :green}]]}
]

Part 1

config = %{
  :red => 12,
  :green => 13,
  :blue => 14
}
%{green: 13, red: 12, blue: 14}
defmodule Bag do
  def validate(rounds, config) do
    res =
      rounds
      |> Enum.map(fn round ->
        invalid =
          round
          |> Enum.find(fn {amount, color} ->
            amount > config[color]
          end)

        is_nil(invalid)
      end)

    Enum.all?(res)
  end
end
{:module, Bag, <<70, 79, 82, 49, 0, 0, 8, ...>>, {:validate, 2}}
input
|> Enum.map(fn {game_id, rounds} ->
  {game_id, Bag.validate(rounds, config)}
end)
|> Enum.filter(fn {_, is_valid} -> is_valid end)
|> Enum.map(&amp;elem(&amp;1, 0))
|> Enum.sum()
8

Part 2

defmodule CounterBag do
  def minimum(rounds) do
    min = %{
      :red => 0,
      :green => 0,
      :blue => 0
    }

    Enum.reduce(rounds, min, fn round, min ->
      Enum.reduce(round, min, fn {amount, color}, min ->
        if amount > min[color] do
          Map.replace!(min, color, amount)
        else
          min
        end
      end)
    end)
  end
end
{:module, CounterBag, <<70, 79, 82, 49, 0, 0, 8, ...>>, {:minimum, 1}}
input
|> Enum.map(fn {_, rounds} ->
  CounterBag.minimum(rounds)
  |> Map.values()
  |> Enum.reduce(fn x, acc -> x * acc end)
end)
|> Enum.sum()
2286