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

--- Day 7: Bridge Repair ---

2024/day_7.livemd

— Day 7: Bridge Repair —

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

Setup

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "7", System.fetch_env!("LB_AOC_SESSION_COOKIE"))
test = Kino.Input.textarea("test")
defmodule BridgeRepair do
  import String, only: [split: 3, split: 2, to_integer: 1]

  def parse(input) do
    input
    |> split("\n")
    |> Enum.map(fn line ->
      [result, vars] = split(line, ":")

      {to_integer(result), vars |> split(" ", trim: true) |> Enum.map(&to_integer/1)}
    end)
  end

  def equations(vars, funcs) do
    operations = permutations(funcs, length(vars) - 1)

    for ops <- operations do
      vars
      |> Enum.zip(ops)
      |> Kernel.++([List.last(vars)])
      |> Enum.map(fn
        {_, _} = t -> Tuple.to_list(t)
        v -> v
      end)
      |> List.flatten()
    end
  end

  def do_math(equation) do
    [x, func, y | rest] = equation

    rest
    |> Enum.chunk_every(2)
    |> Enum.reduce(func.(x, y), fn [func, n], acc -> func.(acc, n) end)
  end

  def permutations(list), do: permutations(list, length(list))
  def permutations([], _), do: [[]]
  def permutations(_, 0), do: [[]]
  def permutations(list, i), do: for(x <- list, y <- permutations(list, i - 1), do: [x | y])

  def concat(x, y), do: String.to_integer(Integer.to_string(x) <> Integer.to_string(y))
end

Part 1

import BridgeRepair
test_input = Kino.Input.read(test)

puzzle_input
|> parse()
|> Enum.map(fn
  {result, vars} ->
    vars
    |> equations([&amp;+/2, &amp;*/2])
    |> Enum.reduce_while(0, fn equation, _acc ->
      calc = do_math(equation)
      if calc == result, do: {:halt, calc}, else: {:cont, 0}
    end)
end)
|> Enum.sum()

Part 2

import BridgeRepair
test_input = Kino.Input.read(test)

puzzle_input
|> parse()
|> Enum.map(fn
  {result, vars} ->
    vars
    |> equations([&amp;+/2, &amp;*/2, &amp;concat/2])
    |> Enum.reduce_while(0, fn equation, _acc ->
      calc = do_math(equation)
      if calc == result, do: {:halt, calc}, else: {:cont, 0}
    end)
end)
|> Enum.sum()