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