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

2022 Day 3

day_03.livemd

2022 Day 3

Mix.install([:kino])

Input

Run in Livebook

input = Kino.Input.textarea("Puzzle Input")

Code

Module

defmodule RuckSack do
  def priorities(input) do
    input
    |> process_input()
    |> Enum.map(
      &(&1
        |> compartments()
        |> get_diff()
        |> priority())
    )
    |> Enum.sum()
  end

  def badges(input) do
    input
    |> process_input()
    |> Enum.chunk_every(3)
    |> Enum.map(
      &(&1
        |> get_badge()
        |> priority())
    )
    |> Enum.sum()
  end

  defp compartments(list) do
    Enum.split(
      list,
      list
      |> Enum.count()
      |> Kernel.div(2)
    )
  end

  defp get_diff({comp1, comp2}) do
    MapSet.new(comp1)
    |> MapSet.intersection(MapSet.new(comp2))
    |> Enum.at(0)
  end

  defp get_badge([sack1, sack2, sack3]) do
    MapSet.new(sack1)
    |> MapSet.intersection(MapSet.new(sack2))
    |> MapSet.intersection(MapSet.new(sack3))
    |> Enum.at(0)
  end

  # A-Z in erlang is 65..90
  # a-z in erlang is 97..122
  defp priority(char) when char in 65..90, do: char - 38
  defp priority(char) when char in 97..122, do: char - 96

  defp process_input(input) do
    input
    |> String.split()
    |> Enum.map(&String.to_charlist/1)
  end
end

Evaluate

part_1 =
  input
  |> Kino.Input.read()
  |> RuckSack.priorities()

part_2 =
  input
  |> Kino.Input.read()
  |> RuckSack.badges()

{part_1, part_2}

Test

ExUnit.start(autorun: false)

defmodule RuckSackTest do
  use ExUnit.Case, async: true

  setup do
    # paste your example data after line 8
    input = ~s(
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
)

    {:ok, input: input}
  end

  test "priorities", %{input: input} do
    assert RuckSack.priorities(input) == 157
  end

  test "badges", %{input: input} do
    assert RuckSack.badges(input) == 70
  end
end

ExUnit.run()