defmodule Aoc2024.Day07 do def parse(input) do input |> String.split("\n", trim: true) |> Enum.map(fn x -> x |> String.split(": ") |> Enum.into([]) end) |> Enum.map(fn [x, y] -> {String.to_integer(x), y |> String.split(" ") |> Enum.map(&String.to_integer/1)} end) |> Enum.into([]) end def part1(input) do input |> Enum.map(fn {target, numbers} -> Task.async(fn -> compute(target, numbers) end) end) |> Enum.map(&Task.await/1) |> Enum.filter(&Kernel.is_integer/1) |> Enum.sum() end defp compute(target, numbers), do: compute(target, Enum.reverse(numbers), target) defp compute(_, _, current) when current < 0, do: nil defp compute(target, [], 0), do: target defp compute(_, _, 0), do: nil defp compute(_, [], _), do: nil defp compute(target, [x | numbers], current) do if rem(current, x) == 0 do if compute(target, numbers, div(current, x)) == target do target else compute(target, numbers, current - x) end else compute(target, numbers, current - x) end end def part2(input) do input |> Enum.map(fn {target, numbers} -> Task.async(fn -> compute2(target, numbers) end) end) |> Enum.map(&Task.await/1) |> Enum.filter(&Kernel.is_integer/1) |> Enum.sum() end defp compute2(target, numbers), do: compute2(target, Enum.reverse(numbers), target) defp compute2(_, _, current) when current < 0, do: nil defp compute2(target, [], 0), do: target defp compute2(_, _, 0), do: nil defp compute2(_, [], _), do: nil defp compute2(target, [x | numbers], current) do s_c = current |> Integer.to_string() s_x = x |> Integer.to_string() nc = s_c |> String.replace_suffix(s_x, "") cond do s_c |> String.ends_with?(s_x) and nc != "" and compute2(target, numbers, nc |> String.to_integer()) == target -> target rem(current, x) == 0 and compute2(target, numbers, div(current, x)) == target -> target true -> compute2(target, numbers, current - x) end end end