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

Day 5: Print Queue

2024/day_05.livemd

Day 5: Print Queue

Mix.install([:kino])

input = Kino.Input.textarea("Please paste your input:")

Part 1

Run in Livebook

https://adventofcode.com/2024/day/5

data =
  input
  |> Kino.Input.read()
  |> String.split("\n\n", trim: true)
  |> Enum.map(& &1 |> String.split("\n", trim: true))
[rule_data, update_data] = data

rules =
  rule_data
  |> Enum.map(fn str -> str |> String.split("|") |> Enum.map(&String.to_integer/1) end)

updates =
  update_data
  |> Enum.map(fn str -> str |> String.split(",") |> Enum.map(&String.to_integer/1) end)

rule_af_bfs_map =
  rules
  |> Enum.group_by(fn [_bf, af] -> af end, fn [bf, _af] -> bf end)

do_check_rule_fun = fn
  _updated, [] = _queue, _recur_fun ->
    true

  updated, [h | t] = queue, recur_fun ->
    bfs = rule_af_bfs_map |> Map.get(h, [])

    case bfs |> Enum.any?(&(&1 in queue)) do
      true -> false
      _ -> recur_fun.(updated ++ [h], t, recur_fun)
    end
end

check_rule_fun = fn update ->
  do_check_rule_fun.([], update, do_check_rule_fun)
end

get_mid_fun = fn update ->
  mid_index = div(Enum.count(update), 2)

  update |> Enum.at(mid_index)
end

_answer =
  updates
  |> Enum.filter(check_rule_fun)
  |> Enum.map(get_mid_fun)
  |> Enum.sum()

Part 2

https://adventofcode.com/2024/day/5#part2

do_correct_update_fun = fn
  [], acc, _recur_fun ->
    acc

  remains, acc, recur_fun ->
    IO.inspect({remains, acc}, charlists: :as_lists)

    h =
      remains
      |> Enum.find(fn remain ->
        bfs = rule_af_bfs_map |> Map.get(remain, [])

        bfs -- remains == bfs
      end)

    recur_fun.(remains -- [h], [h | acc], recur_fun)
end

correct_update_fun = fn update ->
  do_correct_update_fun.(update, [], do_correct_update_fun)
end

_answer =
  updates
  |> Enum.reject(check_rule_fun)
  |> Enum.map(correct_update_fun)
  |> Enum.map(get_mid_fun)
  |> Enum.sum()