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

Advent of Code - 2024 Day 7

2024/day-07.livemd

Advent of Code - 2024 Day 7

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

Part 1

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "7", System.fetch_env!("LB_AOC_SESSION"))
lines =
  puzzle_input
  |> String.split("\n")
  |> Enum.map(&String.split(&1, ~r/\D+/, trim: true))
  |> Enum.map(fn nums -> Enum.map(nums, &String.to_integer/1) end)
  |> Enum.map(fn [result | operands] ->
    {result, Enum.reverse(operands)}
  end)
defmodule AoC2024.Day07 do
  def part_1(input) do
    input
    |> Enum.filter(fn {result, rev_operands} ->
      solvable_1?(result, rev_operands)
    end)
    |> Enum.map(&elem(&1, 0))
    |> Enum.sum()
  end

  def part_2(input) do
    input
    |> Enum.filter(fn {result, rev_operands} ->
      solvable_2?(result, rev_operands)
    end)
    |> Enum.map(&elem(&1, 0))
    |> Enum.sum()
  end

  defp solvable_1?(target, []) do
    target == 0
  end

  defp solvable_1?(target, [h | t]) do
    solvable_1?(target - h, t) or
    (rem(target, h) == 0 and solvable_1?(div(target, h), t))
  end

  defp solvable_2?(target, []) do
    target == 0
  end
  
  defp solvable_2?(target, [h | t]) do
    solvable_2?(target - h, t) or
    (rem(target, h) == 0 and solvable_2?(div(target, h), t)) or
    ((truncated = truncate(target, h)) && solvable_2?(truncated, t))
  end

  defp truncate(a, b) when a < b, do: false

  defp truncate(a, 0), do: a

  defp truncate(a, b) when rem(a, 10) != rem(b, 10), do: false

  defp truncate(a, b) do
    truncate(div(a, 10), div(b, 10))
  end
end
AoC2024.Day07.part_1(lines)
AoC2024.Day07.part_2(lines)