Powered by AppSignal & Oban Pro

Advent of code day 15

2023/livebooks/day-15.livemd

Advent of code day 15

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

Setup input

example = Kino.Input.textarea("Please paste your input example:")
input = Kino.Input.textarea("Please paste your real input:")
defmodule Hash do
  def hash(string) do
    Enum.reduce(string |> String.split("", trim: true), 0, fn s, current_value ->
      current_value = :binary.first(s) + current_value
      current_value = current_value * 17 
      rem(current_value, 256)
    end)
  end
end

Part 01

example
  |> Kino.Input.read()
  |> String.split(",")
  |> Enum.map(&Hash.hash/1)
  |> Enum.sum

Part 02

boxes =
  for _b <- 0..265 do
    []
  end
  |> List.to_tuple()

focal_lengths = %{}

{boxes, focal_lengths} =
  example
  |> Kino.Input.read()
  |> String.split(",")
  |> Enum.reduce({boxes, focal_lengths}, fn instruction, {boxes, focal_lengths} ->
    [label, op, len] =
      String.split(instruction, ~r/(=|-)/, include_captures: true, trim: true)
      |> case do
        [label, op, len] -> [label, op, String.to_integer(len)]
        [label, op] -> [label, op, 0]
      end

    index = Hash.hash(label)

    case op do
      "-" ->
        boxes = update_in(boxes, [Access.elem(index)], &amp;List.delete(&amp;1, label))
        {boxes, focal_lengths}

      "=" ->
        boxes =
          update_in(boxes, [Access.elem(index)], fn bb ->
            if label in bb, do: bb, else: bb ++ [label]
          end)

        focal_lengths = Map.put(focal_lengths, label, len)
        {boxes, focal_lengths}
    end
  end)

boxes
|> Tuple.to_list()
|> Enum.with_index(1)
|> Enum.reduce(0, fn {box, box_number}, total ->
  box
  |> Enum.with_index(1)
  |> Enum.reduce(total, fn {label, label_idx}, total ->
    total + box_number * label_idx * focal_lengths[label]
  end)
end)