# Day 4
```elixir
Mix.install([
{:kino, "~> 0.11.3"}
])
```
## Solutions
```elixir
input = Kino.Input.textarea("Please paste your input file:")
```
### Day 4: Scratchcards
For example:
```
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
```
tldr; find winning number count for each card double for the second, double again for third, etc. add up points.
So, in this example, the Elf's pile of scratchcards is worth `13` points.
### Part Two
tldr; number of winning numbers on card 1 gives you free cards:
* Card 1 has four matching numbers, so you win one copy each of the next four cards: cards 2, 3, 4, and 5.
* Repeat for card 2, etc.
In total, this example pile of scratchcards causes you to ultimately have `30` scratchcards!
```elixir
input = Kino.Input.read(input)
defmodule Y2023.D4 do
@moduledoc """
https://adventofcode.com/2023/day/4
"""
def p1(input) do
input
|> parse_input()
|> Enum.map(&find_match_count/1)
|> Enum.map(&calculate_points/1)
|> Enum.sum()
end
def parse_input(input) do
input
|> String.split("\n", trim: true)
|> Enum.map(&String.trim/1)
end
def find_match_count(card) do
[_, winning_numbers, owned_numbers] = Regex.run(~r/^.+:([\s\d]+)\|([\d\s]+)/, card)
parse_numbers(winning_numbers)
|> MapSet.intersection(parse_numbers(owned_numbers))
|> MapSet.size()
end
defp calculate_points(winning_count) do
(2 ** (winning_count - 1)) |> trunc()
end
def parse_numbers(numbers_string) do
numbers_string
|> String.split(" ", trim: true)
|> MapSet.new()
end
def p2(input) do
input
|> parse_input()
|> Enum.map(&find_match_count/1)
|> Enum.map(&initialize_card/1)
|> claim_winning_cards()
|> Enum.reduce(0, fn {_bonus, count}, acc -> acc + count end)
end
def initialize_card(bonus) do
{bonus, 1}
end
def claim_winning_cards([]), do: []
def claim_winning_cards([{bonus, count} = card | rest]) do
{bonus_cards, remaining_cards} = Enum.split(rest, bonus)
rest_cards = apply_bonus(bonus_cards, count) ++ remaining_cards
[card | claim_winning_cards(rest_cards)]
end
def apply_bonus(cards, count) do
Enum.map(cards, fn {bonus, card_count} -> {bonus, card_count + count} end)
end
end
Y2023.D4.p1(input) |> IO.puts()
Y2023.D4.p2(input) |> IO.puts()
```
### Observations
The part 1 and part 2 of each exercise help you think about how the code you write might be used in the future when requirements change. Yesterday, I had almost no reuse between parts 1 and 2. Today, I was able to reuse a good chunk of it.