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(&String.trim/1)
|> Enum.map(fn draw ->
draw
|> String.split(", ")
|> Enum.reduce(@colors |> Enum.map(&{&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, &(&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(& &1[color]) |> Enum.max()}
end)
end
def power_of(set), do: Enum.reduce(@colors, 1, &(&2 * set[&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(&DrawsParser.parse_line/1)
|> Enum.filter(&DrawsParser.is_possible_given(&1, red: 12, green: 13, blue: 14))
|> Stream.map(& &1.game)
|> Enum.sum()
# should be 8
Path.join(__DIR__, "day-2.input")
|> File.stream!()
|> Stream.map(&DrawsParser.parse_line/1)
|> Stream.filter(&DrawsParser.is_possible_given(&1, red: 12, green: 13, blue: 14))
|> Stream.map(& &1.game)
|> Enum.sum()
example_input
|> String.split("\n", trim: true)
|> Stream.map(&DrawsParser.parse_line/1)
|> Stream.map(&DrawsParser.minimum_set_of/1)
|> Stream.map(&DrawsParser.power_of/1)
|> Enum.sum()
# should be 2286
Path.join(__DIR__, "day-2.input")
|> File.stream!()
|> Stream.map(&DrawsParser.parse_line/1)
|> Stream.map(&DrawsParser.minimum_set_of/1)
|> Stream.map(&DrawsParser.power_of/1)
|> Enum.sum()