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

2022 - day 13

2022/elixir/day-13.livemd

2022 - day 13

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

Section

input = Kino.Input.textarea("")
input_1 = Kino.Input.textarea("")
defmodule Part1 do
  def solve(input) do
    input
    |> String.split("\n")
    |> Enum.map(fn line -> Code.string_to_quoted!(line) end)
    |> Enum.chunk_every(2, 3)
    |> Enum.with_index(1)
    |> Enum.flat_map(fn {[left, right], i} ->
      case check_order(left, right) do
        :right -> [i]
        _ -> []
      end
    end)
    |> Enum.sum()
  end

  def check_order(left, right) when is_integer(left) and is_integer(right) do
    cond do
      left < right -> :right
      left == right -> :cont
      true -> :not_right
    end
  end

  def check_order(left, right) when is_integer(left), do: check_order([left], right)
  def check_order(left, right) when is_integer(right), do: check_order(left, [right])
  def check_order([], [_ | _]), do: :right
  def check_order([_ | _], []), do: :not_right
  def check_order([], []), do: :cont

  def check_order([l | lrest], [r | rrest]) do
    case check_order(l, r) do
      :cont -> check_order(lrest, rrest)
      otherwise -> otherwise
    end
  end
end

input
|> Kino.Input.read()
|> Part1.solve()
defmodule Comparator do
  @spec compare(list() | integer(), list() | integer()) :: :lt | :gt | :eq
  def compare(left, right) when is_integer(left) and is_integer(right) do
    cond do
      left < right -> :lt
      left == right -> :eq
      true -> :gt
    end
  end

  def compare(left, right) when is_integer(left), do: compare([left], right)
  def compare(left, right) when is_integer(right), do: compare(left, [right])
  def compare([], [_ | _]), do: :lt
  def compare([_ | _], []), do: :gt
  def compare([], []), do: :eq

  def compare([l | lrest], [r | rrest]) do
    case compare(l, r) do
      :eq -> compare(lrest, rrest)
      otherwise -> otherwise
    end
  end
end

defmodule Part2 do
  def solve(input) do
    input
    |> String.split("\n")
    |> Enum.reject(&amp;(&amp;1 == ""))
    |> Enum.map(fn line -> Code.string_to_quoted!(line) end)
    |> List.insert_at(0, [[2]])
    |> List.insert_at(0, [[6]])
    |> Enum.sort(Comparator)
    |> find_dividers()
  end

  defp find_dividers(list) do
    first = Enum.find_index(list, &amp;(&amp;1 == [[2]])) + 1
    second = Enum.find_index(list, &amp;(&amp;1 == [[6]])) + 1
    first * second
  end
end

input
|> Kino.Input.read()
|> Part2.solve()