Run this notebook

Use Livebook to open this notebook and explore new ideas.

It is easy to get started, on your machine or the cloud.

Click below to open and run it in your Livebook at .

(or change your Livebook location)

# 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.
See source

Have you already installed Livebook?

If you already installed Livebook, you can configure the default Livebook location where you want to open notebooks.
Livebook up Checking status We can't reach this Livebook (but we saved your preference anyway)
Run notebook

Not yet? Install Livebook in just a minute

Livebook is open source, free, and ready to run anywhere.

Run on your machine

with Livebook Desktop

Run in the cloud

on select platforms

To run on Linux, Docker, embedded devices, or Elixir’s Mix, check our README.

PLATINUM SPONSORS
SPONSORS
Code navigation with go to definition of modules and functions Read More ×