Day 4: Scratchcards
Mix.install([:kino])
input = Kino.Input.textarea("Please paste your input:")
Part 1
https://adventofcode.com/2023/day/4
data =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
cards =
data
|> Enum.map(fn card_str ->
%{"winning_numbers_str" => winning_numbers_str, "numbers_str" => numbers_str} =
Regex.named_captures(
~r/Card\s+\d+:(?.+)\|(?.+)/,
card_str
)
winning_numbers =
winning_numbers_str
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
numbers =
numbers_str
|> String.split(" ", trim: true)
|> Enum.map(&String.to_integer/1)
%{winning_numbers: winning_numbers, numbers: numbers}
end)
cards
|> Enum.map(fn %{winning_numbers: winning_numbers, numbers: numbers} ->
match_count =
MapSet.intersection(MapSet.new(winning_numbers), MapSet.new(numbers))
|> Enum.count()
case match_count do
0 -> 0
match_count -> 2 ** (match_count - 1)
end
end)
|> Enum.sum()
Part 2
https://adventofcode.com/2023/day/4#part2
{_, card_count} =
cards
|> Enum.with_index()
|> Enum.reduce({%{}, 0}, fn {%{winning_numbers: winning_numbers, numbers: numbers}, i},
{copies, sum} ->
match_count =
MapSet.intersection(MapSet.new(winning_numbers), MapSet.new(numbers))
|> Enum.count()
card_count = Map.get(copies, i, 0) + 1
new_copies =
1..match_count//1
|> Enum.reduce(copies, fn x, copies ->
copies |> Map.update(i + x, card_count, &(&1 + card_count))
end)
new_sum = sum + card_count
{new_copies, new_sum}
end)
card_count