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

Advent of Code 2023 - Day 2

2023/aoc23.02.livemd

Advent of Code 2023 - Day 2

Intro

We’re playing a guessing game involving at most 12 red cubes, 13 green cubes, and 14 blue cubes. We need to figure out which games are possible given these restrictions.

Prompt: https://imagine.meta.com/?prompt=cartoonish+elf+with+a+bag+of+red%2C+green%2C+and+blue+cubes

Input Parsing

## given test 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

to_map = fn draw ->
  draw
  |> String.split(", ")
  |> Enum.map(&String.split/1)
  |> Enum.map(fn [a, b] -> {b, Integer.parse(a) |> elem(0)} end)
  |> Map.new()
end

to_maps = fn draws ->
  draws
  |> Enum.map(to_map)
end

# We're discarding the "Game X: " prefix because we can recreate it with `with_index` later
input =
  File.read!(File.cwd!() <> "/code/advent_of_code/aoc2023/day02.input")
  |> String.split("\r\n")
  |> Enum.map(&amp;(String.split(&amp;1, ": ") |> Enum.at(-1)))
  |> Enum.map(&amp;String.split(&amp;1, "; "))
  |> Enum.map(to_maps)

Part 1

We need the sum of game numbers that are possible given there are only 12 red cubes, 13 green cubes, and 14 blue cubes.

possible? = fn draw ->
  Map.get(draw, "red", 0) <= 12 and
    Map.get(draw, "green", 0) <= 13 and
    Map.get(draw, "blue", 0) <= 14
end

input
|> Stream.map(&amp;Enum.all?(&amp;1, possible?))
|> Stream.with_index(1)
|> Stream.filter(&amp;elem(&amp;1, 0))
|> Stream.map(&amp;elem(&amp;1, 1))
|> Enum.sum()

Part 2

We need to find the fewest number of cubes of each color to make the game possible. The “power” of each game is the product of those counts.

For each game, we get the maximum of each color, multiply them together, and then sum everything.

maximums = fn m, acc ->
  Map.update!(acc, "blue", fn x -> max(x, Map.get(m, "blue", 0)) end)
  |> Map.update!("green", fn x -> max(x, Map.get(m, "green", 0)) end)
  |> Map.update!("red", fn x -> max(x, Map.get(m, "red", 0)) end)
end

power = fn game ->
  Enum.reduce(game, %{"blue" => 0, "red" => 0, "green" => 0}, maximums)
  |> Map.values()
  |> Enum.product()
end

input
|> Stream.map(power)
|> Enum.sum()