Powered by AppSignal & Oban Pro

day 05

2020/livebooks/day-05.livemd

day 05

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

Section

input = Kino.Input.textarea("paste")
example = Kino.Input.textarea("paste")

Helper

defmodule BinarySearch do
  def seat_code(ticket) do
    row = binary_part(ticket, 0, 7)
    col = binary_part(ticket, 7, 3)
    get_row(row) * 8 + get_col(col)
  end

  defp get_row(ticket) do
    binary_search(
      String.to_charlist(ticket),
      0,
      127
    )
  end

  defp get_col(ticket) do
    binary_search(
      String.to_charlist(ticket),
      0,
      7,
      :col
    )
  end

  # ROWS
  defp binary_search([], start, _final), do: start

  defp binary_search([?F | rest], start, final) do
    binary_search(rest, start, get_mid_point(start, final) - 1)
  end

  defp binary_search([?B | rest], start, final) do
    binary_search(rest, get_mid_point(start, final) + 1, final)
  end

  # COLUMNS
  defp binary_search([], _, final, :col), do: final

  defp binary_search([?R | rest], start, final, :col) do
    binary_search(rest, get_mid_point(start, final), final, :col)
  end

  defp binary_search([?L | rest], start, final, :col) do
    binary_search(rest, start, get_mid_point(start, final), :col)
  end

  # HELPERS
  defp get_mid_point(start, final) do
    div(final + start, 2)
  end
end

Part 01

lines =
  input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.reduce(0, fn ticket, acc ->
    seat_code = BinarySearch.seat_code(ticket)

    max(seat_code, acc)
  end)

Part 02

seats =
  input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.map(fn ticket ->
    BinarySearch.seat_code(ticket)
  end)

possible_tickets =
  for row <- 1..126,
      col <- 1..6,
      (row * 8 + col) not in seats do
    row * 8 + col
  end

possible_tickets
|> Enum.chunk_every(3, 1, :discard)
|> Enum.filter(fn [a, b, c] -> a + 1 != b &amp;&amp; b + 1 != c end)
|> hd()
|> then(fn [_, seat, _] -> seat end)