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

Day 2: Cube Conundrum

day-2.livemd

Day 2: Cube Conundrum

Part one

defmodule DrawsParser do
  defmodule Game do
    defstruct [:game, :draws]
  end

  @colors ~w(red green blue)a

  def parse_line(line) do
    ["Game " <> game_string | draws] = Regex.split(~r/:|;/, line)

    draws =
      draws
      |> Enum.map(&amp;String.trim/1)
      |> Enum.map(fn draw ->
        draw
        |> String.split(", ")
        |> Enum.reduce(@colors |> Enum.map(&amp;{&amp;1, 0}), fn cubes, acc ->
          [amount, color] = String.split(cubes, " ")
          amount = String.to_integer(amount)
          color = String.to_atom(color)
          Keyword.update(acc, color, amount, &amp;(&amp;1 + amount))
        end)
      end)

    %DrawsParser.Game{game: String.to_integer(game_string), draws: draws}
  end

  def is_possible_given(%DrawsParser.Game{draws: draws}, spec) do
    Enum.all?(draws, fn draw ->
      Enum.all?(@colors, fn color ->
        draw[color] <= spec[color]
      end)
    end)
  end

  def minimum_set_of(%DrawsParser.Game{draws: draws}) do
    @colors
    |> Enum.map(fn color ->
      {color, draws |> Enum.map(&amp; &amp;1[color]) |> Enum.max()}
    end)
  end

  def power_of(set), do: Enum.reduce(@colors, 1, &amp;(&amp;2 * set[&amp;1]))
end
example_input =
  """
  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
  """
example_input
|> String.split("\n", trim: true)
|> Enum.map(&amp;DrawsParser.parse_line/1)
|> Enum.filter(&amp;DrawsParser.is_possible_given(&amp;1, red: 12, green: 13, blue: 14))
|> Stream.map(&amp; &amp;1.game)
|> Enum.sum()

# should be 8
Path.join(__DIR__, "day-2.input")
|> File.stream!()
|> Stream.map(&amp;DrawsParser.parse_line/1)
|> Stream.filter(&amp;DrawsParser.is_possible_given(&amp;1, red: 12, green: 13, blue: 14))
|> Stream.map(&amp; &amp;1.game)
|> Enum.sum()

Part two

example_input
|> String.split("\n", trim: true)
|> Stream.map(&amp;DrawsParser.parse_line/1)
|> Stream.map(&amp;DrawsParser.minimum_set_of/1)
|> Stream.map(&amp;DrawsParser.power_of/1)
|> Enum.sum()

# should be 2286
Path.join(__DIR__, "day-2.input")
|> File.stream!()
|> Stream.map(&amp;DrawsParser.parse_line/1)
|> Stream.map(&amp;DrawsParser.minimum_set_of/1)
|> Stream.map(&amp;DrawsParser.power_of/1)
|> Enum.sum()