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

Day 3

day_03/day_3.livemd

Day 3

Mix.install([
  {:kino, "~> 0.7.0"}
])

Section

text_area_input = Kino.Input.textarea("input")
defmodule Day3 do
  @input Kino.Input.read(text_area_input)

  a = ?a..?z |> Stream.with_index(1)
  b = ?A..?Z |> Stream.with_index(Enum.count(a) + 1)

  @score Stream.concat(a, b)
         |> Enum.map(fn {c, i} -> {String.Chars.BitString.to_string(<>), i} end)
         |> Enum.reduce(%{}, fn {char, score}, acc ->
           Map.merge(acc, %{char => score})
         end)

  defp parse_input_part_one() do
    @input
    |> String.split("\n")
    |> Enum.map(fn s ->
      String.split_at(s, String.length(s) |> Integer.floor_div(2))
      |> Tuple.to_list()
      |> Enum.map(fn a ->
        String.split(a, "", trim: true)
        |> Enum.frequencies()
      end)
    end)
  end

  defp parse_input_part_two() do
    @input
    |> String.split("\n")
    |> Enum.map(fn s ->
      String.split(s, "", trim: true)
      |> Enum.frequencies()
    end)
    |> Enum.chunk_every(3)
  end

  defp find_dup([map1, map2]) do
    Map.keys(map1)
    |> Enum.reduce_while(nil, fn key, acc ->
      cond do
        Map.has_key?(map2, key) -> {:halt, key}
        true -> {:cont, acc}
      end
    end)
  end

  defp find_dup([map1, map2, map3]) do
    Map.keys(map1)
    |> Enum.reduce_while(nil, fn key, acc ->
      cond do
        Map.has_key?(map2, key) and Map.has_key?(map3, key) -> {:halt, key}
        true -> {:cont, acc}
      end
    end)
  end

  defp get_score(char) do
    Map.get(@score, char)
  end

  def result_part_one() do
    parse_input_part_one()
    |> Enum.map(&amp;find_dup/1)
    |> Enum.map(&amp;get_score/1)
    |> Enum.reduce(0, fn score, acc -> score + acc end)
  end

  def result_part_two() do
    parse_input_part_two()
    |> Enum.map(&amp;find_dup/1)
    |> Enum.map(&amp;get_score/1)
    |> Enum.reduce(0, fn score, acc -> score + acc end)
  end
end

Day3.result_part_one()
Day3.result_part_two()
ExUnit.start()

defmodule TestDay3 do
  use ExUnit.Case

  test "part one" do
    assert Day3.result_part_one() == 8176
  end

  test "part two" do
    assert Day3.result_part_two() == 2689
  end
end

ExUnit.run()