Day 2: Cube Conundrum
Mix.install([:kino])
input = Kino.Input.textarea("Please paste your input:")
Part 1
https://adventofcode.com/2023/day/2
game_strs =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
defmodule Day02.Parser do
def parse(game_strs) do
game_strs
|> Enum.map(&parse_game/1)
end
def parse_game(game_str) do
["Game " <> game_id_str, sets_str] = game_str |> String.split(":")
game_id = game_id_str |> String.to_integer()
sets = sets_str |> parse_sets()
{game_id, sets}
end
def parse_sets(sets_str) do
sets_str
|> String.split(";")
|> Enum.map(&parse_set/1)
end
def parse_set(set_str) do
set_str
|> String.split(",")
|> Enum.map(&parse_subset/1)
end
def parse_subset(subset_str) do
{number, color_str} = subset_str |> String.trim() |> Integer.parse()
color = color_str |> String.trim() |> String.to_existing_atom()
{color, number}
end
end
ExUnit.start(auto_run: false)
defmodule Dau02.ParserTest do
use ExUnit.Case, async: true
alias Day02.Parser
test "parse_sets/1" do
assert Parser.parse_sets("3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green") ==
[
[{:blue, 3}, {:red, 4}],
[{:red, 1}, {:green, 2}, {:blue, 6}],
[{:green, 2}]
]
end
test "parse_set/1" do
assert Parser.parse_set("1 red, 2 green, 6 blue") == [{:red, 1}, {:green, 2}, {:blue, 6}]
end
test "parse_subset/1" do
assert Parser.parse_subset("1 red") == {:red, 1}
end
end
ExUnit.run()
alias Day02.Parser
games = game_strs |> Parser.parse()
defmodule Day02.Part1 do
@cubes %{
red: 12,
green: 13,
blue: 14
}
def solve(games) do
games
|> Enum.filter(&possible_game?/1)
|> Enum.map(fn {game_id, _sets} -> game_id end)
|> Enum.sum()
end
defp possible_game?({_game_id, sets}) do
sets
|> Enum.all?(&possible_set?/1)
end
defp possible_set?(set) do
set
|> Enum.all?(&possible_subset?/1)
end
defp possible_subset?({color, number}) do
number <= @cubes[color]
end
end
Day02.Part1.solve(games)
Part 2
https://adventofcode.com/2023/day/2#part2
defmodule Day02.Part2 do
def solve(games) do
games
|> Enum.map(&calc_mins/1)
|> Enum.map(fn mins -> mins |> Map.values() |> Enum.product() end)
|> Enum.sum()
end
defp calc_mins({_game_id, sets}) do
sets
# |> Enum.reduce(%{}, fn set, mins ->
# set
# |> Enum.reduce(mins, fn {color, number}, mins ->
# mins |> Map.update(color, number, & max(&1, number))
# end)
# end)
|> List.flatten()
|> Enum.reduce(%{}, fn {color, number}, mins ->
mins |> Map.update(color, number, &max(&1, number))
end)
end
end
Day02.Part2.solve(games)