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

Day 24: It Hangs in the Balance

day_24_it_hangs_in_the_balance.livemd

Day 24: It Hangs in the Balance

Section

defmodule Santa do
  def solve(weights) do
    total_weight = Enum.sum(weights)

    if rem(total_weight, 3) != 0 do
      raise "The total weight is not divisible by 3"
    end

    target_weight = div(total_weight, 3)

    Stream.iterate(1, &(&1 + 1))
    |> Stream.take_while(&amp;(&amp;1 <= length(weights)))
    |> Stream.flat_map(fn n -> combinations(weights, n) end)
    |> Stream.filter(fn comb -> Enum.sum(comb) == target_weight end)
    |> Enum.reduce_while(nil, fn group1, _acc ->
      remaining_weights = weights -- group1

      if find_valid_group(remaining_weights, target_weight) do
        {:halt, quantum_entanglement(group1)}
      else
        {:cont, nil}
      end
    end)
  end

  defp find_valid_group(weights, target_weight) do
    Stream.iterate(1, &amp;(&amp;1 + 1))
    |> Stream.take_while(&amp;(&amp;1 <= length(weights)))
    |> Stream.flat_map(fn n -> combinations(weights, n) end)
    |> Stream.filter(fn comb -> Enum.sum(comb) == target_weight end)
    |> Enum.any?(fn group2 ->
      remaining_weights2 = weights -- group2
      Enum.sum(remaining_weights2) == target_weight
    end)
  end

  defp combinations(list, n) do
    combinations(list, n, [])
  end

  defp combinations([], _, acc), do: [Enum.reverse(acc)]
  defp combinations(_, 0, acc), do: [Enum.reverse(acc)]

  defp combinations([h | t], n, acc) do
    with_h = combinations(t, n - 1, [h | acc])
    without_h = combinations(t, n, acc)
    with_h ++ without_h
  end

  defp quantum_entanglement(group) do
    Enum.reduce(group, 1, &amp;*/2)
  end
end

"/Users/eli/Desktop/input.txt"
|> File.read!()
|> String.split("\n", trim: true)
|> Enum.map(fn x -> String.to_integer(x) end)
|> Santa.solve()
10723906903
defmodule Santa2 do
  def solve(weights) do
    total_weight = Enum.sum(weights)

    if rem(total_weight, 4) != 0 do
      raise "The total weight is not divisible by 4"
    end

    target_weight = div(total_weight, 4)

    Stream.iterate(1, &amp;(&amp;1 + 1))
    |> Stream.take_while(&amp;(&amp;1 <= length(weights)))
    |> Stream.flat_map(fn n -> combinations(weights, n) end)
    |> Stream.filter(fn comb -> Enum.sum(comb) == target_weight end)
    |> Enum.reduce_while(nil, fn group1, _acc ->
      remaining_weights = weights -- group1

      if find_valid_group(remaining_weights, target_weight) do
        {:halt, quantum_entanglement(group1)}
      else
        {:cont, nil}
      end
    end)
  end

  defp find_valid_group(weights, target_weight) do
    Stream.iterate(1, &amp;(&amp;1 + 1))
    |> Stream.take_while(&amp;(&amp;1 <= length(weights)))
    |> Stream.flat_map(fn n -> combinations(weights, n) end)
    |> Stream.filter(fn comb -> Enum.sum(comb) == target_weight end)
    |> Enum.any?(fn group2 ->
      remaining_weights2 = weights -- group2

      Stream.iterate(1, &amp;(&amp;1 + 1))
      |> Stream.take_while(&amp;(&amp;1 <= length(remaining_weights2)))
      |> Stream.flat_map(fn n -> combinations(remaining_weights2, n) end)
      |> Stream.filter(fn comb -> Enum.sum(comb) == target_weight end)
      |> Enum.any?(fn group3 ->
        remaining_weights3 = remaining_weights2 -- group3
        Enum.sum(remaining_weights3) == target_weight
      end)
    end)
  end

  defp combinations(list, n) do
    combinations(list, n, [])
  end

  defp combinations([], _, acc), do: [Enum.reverse(acc)]
  defp combinations(_, 0, acc), do: [Enum.reverse(acc)]

  defp combinations([h | t], n, acc) do
    with_h = combinations(t, n - 1, [h | acc])
    without_h = combinations(t, n, acc)
    with_h ++ without_h
  end

  defp quantum_entanglement(group) do
    Enum.reduce(group, 1, &amp;*/2)
  end
end

"/Users/eli/Desktop/input.txt"
|> File.read!()
|> String.split("\n", trim: true)
|> Enum.map(fn x -> String.to_integer(x) end)
|> Santa2.solve()
74850409