Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Day 15

2023/day15.livemd

Day 15

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

Section

input = Kino.Input.textarea("Input", monospace: true)
defmodule HASH do
  def box(label) do
    for <>, reduce: 0 do
      hash ->
        rem(17 * (hash + c), 256)
    end
  end
end

defmodule HASHMAP do
  def add(hashmap, label, focal_length) do
    Map.update(
      hashmap,
      HASH.box(label),
      Keyword.new([{String.to_atom(label), focal_length}]),
      fn lenses ->
        Keyword.update(lenses, String.to_atom(label), focal_length, fn _ -> focal_length end)
      end
    )
  end

  def remove(hashmap, label) do
    Map.update(hashmap, HASH.box(label), Keyword.new(), fn lenses ->
      Keyword.delete(lenses, String.to_atom(label))
    end)
  end

  def power(hashmap) do
    Enum.flat_map(hashmap, fn {box, lenses} ->
      Enum.with_index(lenses, fn {_label, focal_length}, slot ->
        (box + 1) * (slot + 1) * focal_length
      end)
    end)
    |> Enum.sum()
  end
end
input
|> Kino.Input.read()
|> String.splitter(",")
|> Stream.map(&amp;HASH.box/1)
|> Enum.sum()
input
|> Kino.Input.read()
|> String.splitter(",")
|> Stream.map(fn str ->
  case String.split(str, ["=", "-"], trim: true) do
    [label] -> {:remove, [label]}
    [label, focal_length] -> {:add, [label, String.to_integer(focal_length)]}
  end
end)
|> Enum.reduce(%{}, fn {op, args}, map ->
  apply(HASHMAP, op, [map | args])
end)
|> HASHMAP.power()