Powered by AppSignal & Oban Pro

Advent of Code 2023 Day 15

2023/day-15.livemd

Advent of Code 2023 Day 15

Mix.install([
  {:kino_aoc, "~> 0.1.5"}
])

Prep

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2023", "15", System.fetch_env!("LB_AOC_SESSION"))
IO.puts(puzzle_input)
import Bitwise
hash = fn string ->
  for <<char <- string>>, reduce: 0 do
    acc -> ((acc + char) <<< 4) + acc + char &&& 0xFF
  end
end
puzzle_input
|> String.split(",")
|> Enum.map(hash)
|> Enum.sum()
instructions =
  puzzle_input
  |> String.split(",")
  |> Enum.map(fn instruction ->
    if String.ends_with?(instruction, "-") do
      key = String.trim_trailing(instruction, "-")
      hkey = hash.(key)

      fn boxes ->
        {box, next_slot} = boxes[hkey]
        box = Map.delete(box, key)
        %{boxes | hkey => {box, next_slot}}
      end
    else
      [key, n] = String.split(instruction, "=")
      hkey = hash.(key)
      n = String.to_integer(n)

      fn boxes ->
        {box, next_slot} = boxes[hkey]

        updated_box =
          Map.update(box, key, {n, next_slot}, fn {_, old_slot} ->
            {n, old_slot}
          end)

        %{boxes | hkey => {updated_box, next_slot + 1}}
      end
    end
  end)
boxes = Map.new(0..255, &{&1, {%{}, 1}})
updated_boxes =
  instructions
  |> Enum.reduce(boxes, & &1.(&2))
  |> Enum.map(fn {hkey, {box, _}} ->
    box
    |> Map.values()
    |> Enum.sort_by(&elem(&1, 1))
    |> Enum.map(&elem(&1, 0))
    |> Enum.with_index(1)
    |> then(&{hkey, &1})
  end)
for {hkey, box} <- updated_boxes, {n, i} <- box, reduce: 0 do
  sum -> sum + (hkey + 1) * n * i
end