Advent of Code 2020 in Elixir - Day 5

Binary Boarding

defmodule Aoc2020.Day5 do
  @moduledoc "Binary Boarding"

  def parse_input() do
    File.read!("priv/inputs/2020/day5.txt")
    |> String.trim()
    |> String.split("\n")
    |> Enum.map(&String.codepoints/1)
    |> Enum.map(&Enum.split(&1, 7))
  end

  def determine_row(_, {row, row}) do
    row
  end

  def determine_row([head | tail], {min, max}) do
    split = floor((max - min) / 2)

    case head do
      "F" -> determine_row(tail, {min, min + split})
      "B" -> determine_row(tail, {max - split, max})
    end
  end

  def determine_column(_, {column, column}) do
    column
  end

  def determine_column([head | tail], {min, max}) do
    split = floor((max - min) / 2)

    case head do
      "L" -> determine_column(tail, {min, min + split})
      "R" -> determine_column(tail, {max - split, max})
    end
  end

  def seat_id(row, column), do: row * 8 + column

  def map_seat_ids(inputs) do
    inputs
    |> Enum.map(fn {rows, cols} ->
      seat_id(
        determine_row(rows, {0, 127}),
        determine_column(cols, {0, 7})
      )
    end)
  end

  def find_missing_id([first | [second | rest]]) do
    if first + 1 != second do
      first + 1
    else
      find_missing_id([second | rest])
    end
  end

  def part_1() do
    parse_input() |> map_seat_ids() |> Enum.max()
  end

  def part_2() do
    parse_input() |> map_seat_ids() |> Enum.sort() |> find_missing_id()
  end

  def run do
    part_2()
  end
end