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

AoC Day 4

2023/day4.livemd

AoC Day 4

Mix.install([
  {:kino, "~> 0.12.2"},
  {:kino_aoc, "~> 0.1.6"}
])

Section

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "4", System.fetch_env!("LB_AOC_SESSION"))
example_input = """
Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3:  1 21 53 59 44 | 69 82 63 72 16 21 14  1
Card 4: 41 92 73 84 69 | 59 84 76 51 58  5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
"""
split = fn input -> String.split(input, " ", trim: true) end

match_counts =
  puzzle_input
  |> String.split("\n", trim: true)
  |> Stream.map(fn line -> String.split(line, [": ", " | "]) end)
  |> Stream.map(fn [_card, left, right] -> {split.(left), split.(right)} end)
  |> Stream.map(fn {winners, numbers} -> winners -- winners -- numbers end)
  |> Stream.map(fn matches -> Enum.count(matches) end)
  |> Enum.with_index(1)

Part 1

match_counts
|> Stream.reject(fn {count, _} -> count <= 0 end)
|> Stream.map(fn {count, _} -> Integer.pow(2, count - 1) end)
|> Enum.sum()

Part 2

for {count, i} <- match_counts,
    count > 0,
    j <- (i + 1)..(i + count),
    reduce: Map.new(match_counts, fn {_, i} -> {i, 1} end) do
  acc -> Map.put(acc, j, acc[j] + acc[i])
end
|> Map.values()
|> Enum.sum()