Advent 2023 - Day 4
Mix.install([
{:kino, "~> 0.11.3"}
])
Section
input = Kino.Input.textarea("Please paste your input file")
input =
input
|> Kino.Input.read()
|> String.split("\n")
|> Enum.map(fn card ->
[card_num, rest] = String.split(card, ": ")
card_num =
card_num
|> String.trim_leading("Card")
|> String.replace(" ", "")
|> Integer.parse()
|> elem(0)
[winning, have] = String.split(rest, " | ")
strip = fn strip ->
strip
|> String.split(" ")
|> Enum.filter(&(&1 != ""))
|> Enum.map(&Integer.parse/1)
|> Enum.map(&elem(&1, 0))
|> MapSet.new()
end
winning = strip.(winning)
have = strip.(have)
{card_num, winning, have}
end)
[
{1, MapSet.new([17, 41, 48, 83, 86]), MapSet.new([6, 9, 17, 31, 48, 53, 83, 86])},
{2, MapSet.new([13, 16, 20, 32, 61]), MapSet.new([17, 19, 24, 30, 32, 61, 68, 82])},
{3, MapSet.new([1, 21, 44, 53, 59]), MapSet.new([1, 14, 16, 21, 63, 69, 72, 82])},
{4, MapSet.new([41, 69, 73, 84, 92]), MapSet.new([5, 51, 54, 58, 59, 76, 83, 84])},
{5, MapSet.new([26, 28, 32, 83, 87]), MapSet.new([12, 22, 30, 36, 70, 82, 88, 93])},
{6, MapSet.new([13, 18, 31, 56, 72]), MapSet.new([10, 11, 23, 35, 36, 67, 74, 77])}
]
cards =
for {card, winning, have} <- input do
count =
for pick <- have do
MapSet.member?(winning, pick)
end
|> Enum.filter(& &1)
|> Enum.count()
{card, count}
end
[{1, 4}, {2, 2}, {3, 2}, {4, 1}, {5, 0}, {6, 0}]
Part 1
for {_card, count} <- cards do
score = Integer.pow(2, count) / 2
floor(score)
end
|> Enum.sum()
13
Part 2
defmodule Scratchcards do
def duplicate(cards) do
duplicate(0, cards)
end
def duplicate(index, cards) do
card = Map.get(cards, index)
if is_nil(card) do
cards
else
{winning, copies} = card
if winning == 0 do
duplicate(index + 1, cards)
else
range = (index + 1)..(index + winning)
cards =
Enum.reduce(range, cards, fn index, cards ->
if Map.has_key?(cards, index) do
Map.get_and_update!(cards, index, fn {other_winning, other_copies} = existing ->
{existing, {other_winning, copies + other_copies}}
end)
|> elem(1)
else
cards
end
end)
duplicate(index + 1, cards)
end
end
end
end
{:module, Scratchcards, <<70, 79, 82, 49, 0, 0, 11, ...>>, {:duplicate, 2}}
cards
|> Enum.map(fn {card_num, winning} -> {card_num - 1, {winning, 1}} end)
|> Map.new()
|> Scratchcards.duplicate()
|> Map.values()
|> Enum.map(&elem(&1, 1))
|> Enum.sum()
30