Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us
Notesclub

Day 4: Scratchcards

day-4.livemd

Day 4: Scratchcards

Part one

sample_input =
  """
  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
  """
defmodule Scratchcards do
  def count_points(input) do
    input
    |> number_of_matches_per_card()
    |> Enum.map(fn
      0 -> 0
      number_of_matches -> Integer.pow(2, number_of_matches - 1)
    end)
    |> Enum.sum()
  end

  def count_scratchcards(input) do
    input
    |> number_of_matches_per_card()
    |> Enum.with_index(1)
    |> Enum.reduce(%{}, fn
      {matches, index}, acc ->
        acc = Map.update(acc, index, 1, &(&1 + 1))

        if matches == 0 do
          acc
        else
          amount = Map.get(acc, index, 0)

          (index + 1)..(index + matches)
          |> Enum.reduce(acc, fn card_nr, acc ->
            Map.update(acc, card_nr, amount, &(&1 + amount))
          end)
        end
    end)
    |> Map.values()
    |> Enum.sum()
  end

  defp number_of_matches_per_card(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.map(fn line ->
      [_, winning_numbers, own_numbers] = Regex.split(~r/:|\|/, line)
      winning_numbers = string_to_list_of_numbers(winning_numbers)
      own_numbers = string_to_list_of_numbers(own_numbers)

      MapSet.intersection(winning_numbers, own_numbers) |> Enum.count()
    end)
  end

  defp string_to_list_of_numbers(string) do
    string |> String.split(" ", trim: true) |> Enum.map(&String.to_integer/1) |> MapSet.new()
  end
end
Scratchcards.count_points(sample_input)
# expect 13
Path.join(__DIR__, "day-4.input")
|> File.read!()
|> Scratchcards.count_points()

# 20829

Part two

Scratchcards.count_scratchcards(sample_input)
# 30
Path.join(__DIR__, "day-4.input")
|> File.read!()
|> Scratchcards.count_scratchcards()

# 12648035