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

Day 15: Lens Library – Advent of Code 2023

2023/15.livemd

Day 15: Lens Library – Advent of Code 2023

input =
  File.read!("/Users/pw/src/weiland/adventofcode/2023/input/15.txt")
  |> String.trim()
  |> String.split(",")

test_input = "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7" |> String.split(",")

Parsing

Part One

hash = fn string ->
  String.to_charlist(string) |> Enum.reduce(0, &rem((&1 + &2) * 17, 256))
end

hash.("HASH") == 52
part_one = fn input ->
  input
  |> Enum.map(&hash.(&1))
  |> Enum.sum()
end

part_one.(test_input) == 1320 &&
  part_one.(input)

Part Two

# unused now
parse_two = fn input ->
  input
  |> Enum.map(fn line ->
    [label, flen] = String.split(line, ~r/[-=]/)

    if flen != "" do
      {:add, hash.(label), label, String.to_integer(flen)}
    else
      {:remove, hash.(label), label}
    end
  end)
end

parse_two.(test_input)
part_two = fn input ->
  input
  |> Enum.reduce(Map.new(), fn line, map ->
    [label, flen] = String.split(line, ~r/[-=]/)
    box = hash.(label)
    lst = Map.get(map, box, [])

    if flen == "" do
      Map.put(map, box, Enum.reject(lst, fn {l, _i} -> l == label end))
    else
      flen = String.to_integer(flen)

      updated =
        if Enum.find(lst, fn {l, _i} -> l == label end),
          do: Enum.map(lst, fn {l, i} -> if l == label, do: {l, flen}, else: {l, i} end),
          else: lst ++ [{label, flen}]

      Map.put(map, box, updated)
    end
  end)
  |> Enum.map(fn {box, lst} ->
    Enum.with_index(lst, fn {_l, focal_length}, i ->
      (box + 1) * (i + 1) * focal_length
    end)
    |> Enum.sum()
  end)
  |> Enum.sum()
end

part_two.(test_input) == 145 &&
  part_two.(input)