Day 04
Mix.install(kino: "~> 0.11")
Common
import Kino.Shorts
input = read_textarea("Puzzle input", monospace: true)
lines = String.split(input, "\n", trim: true)
cards = Enum.map(lines, &Card.parse/1)
defmodule Card do
defstruct [:winning, :numbers]
def parse(entry) do
[_card_str, all_numbers] = String.split(entry, ":")
[winning, numbers] =
all_numbers
|> String.split("|", parts: 2)
|> Enum.map(&parse_numbers/1)
%__MODULE__{
winning: winning,
numbers: numbers
}
end
defp parse_numbers(numbers) do
numbers
|> String.split()
|> Enum.map(&String.to_integer/1)
end
def count_winning(card) do
Enum.count(card.numbers, fn number ->
number in card.winning
end)
end
end
Part 1
cards
|> Stream.map(&Card.count_winning/1)
|> Stream.map(fn
0 -> 0
count -> Integer.pow(2, count - 1)
end)
|> Enum.sum()
Part 2
default_multipliers = List.duplicate(1, Enum.count(cards))
cards
|> Stream.transform(default_multipliers, fn card, [multiplier | others] ->
count_winning = Card.count_winning(card)
{to_update, staying} = Enum.split(others, count_winning)
updated = Enum.map(to_update, &(&1 + multiplier))
{[multiplier], updated ++ staying}
end)
|> Enum.sum()