summaryrefslogtreecommitdiff
path: root/2015/day24.exs
diff options
context:
space:
mode:
Diffstat (limited to '2015/day24.exs')
-rw-r--r--2015/day24.exs96
1 files changed, 96 insertions, 0 deletions
diff --git a/2015/day24.exs b/2015/day24.exs
new file mode 100644
index 0000000..576b8e8
--- /dev/null
+++ b/2015/day24.exs
@@ -0,0 +1,96 @@
+packages =
+ File.stream!("inputs/day24.txt")
+ |> Enum.map(fn line ->
+ {num, ""} = String.trim(line) |> Integer.parse()
+ num
+ end)
+
+defmodule SleighPacker do
+ def canMakeSecondPile(_, 0) do
+ true
+ end
+
+ def canMakeSecondPile([], _) do
+ false
+ end
+
+ def canMakeSecondPile([next | remainingPackages], remainingWeight) do
+ canMakeSecondPile(remainingPackages, remainingWeight - next) ||
+ canMakeSecondPile(remainingPackages, remainingWeight)
+ end
+
+ def packagesCanBeSplitEvenly(rejectedPackages, piles) do
+ weightPerPile = div(Enum.sum(rejectedPackages), piles)
+ # This gave me the right answer for part 2, but that seems to just be a
+ # lucky detail. You probably need to make sure that you can make all of the
+ # remaining piles until it's the last two being split.
+ canMakeSecondPile(rejectedPackages, weightPerPile)
+ end
+
+ def findBestSmallestPile(remainingPackages, 0, rejectedPackages, piles) do
+ if packagesCanBeSplitEvenly(remainingPackages ++ rejectedPackages, piles - 1) do
+ []
+ else
+ nil
+ end
+ end
+
+ def findBestSmallestPile([], _, _, _) do
+ nil
+ end
+
+ def findBestSmallestPile([next | remainingPackages], remainingWeight, rejectedPackages, piles)
+ when next > remainingWeight do
+ findBestSmallestPile(remainingPackages, remainingWeight, [next | rejectedPackages], piles)
+ end
+
+ def findBestSmallestPile([next | remainingPackages], remainingWeight, rejectedPackages, piles) do
+ withNextTail =
+ findBestSmallestPile(remainingPackages, remainingWeight - next, rejectedPackages, piles)
+
+ withNext =
+ if withNextTail == nil do
+ nil
+ else
+ [next | withNextTail]
+ end
+
+ withoutNext =
+ findBestSmallestPile(remainingPackages, remainingWeight, [next | rejectedPackages], piles)
+
+ cond do
+ withNext == nil && withoutNext == nil ->
+ nil
+
+ withNext == nil ->
+ withoutNext
+
+ withoutNext == nil ->
+ withNext
+
+ length(withNext) == length(withoutNext) ->
+ if Enum.product(withNext) < Enum.product(withoutNext) do
+ withNext
+ else
+ withoutNext
+ end
+
+ length(withNext) < length(withoutNext) ->
+ withNext
+
+ true ->
+ withoutNext
+ end
+ end
+
+ def packTheSleigh(packages, piles) do
+ weightPerPile = div(Enum.sum(packages), piles)
+ findBestSmallestPile(packages, weightPerPile, [], piles)
+ end
+end
+
+threePack = SleighPacker.packTheSleigh(packages, 3)
+IO.puts("Product with three piles: #{Enum.product(threePack)}")
+
+fourPack = SleighPacker.packTheSleigh(packages, 4)
+IO.puts("Product with four piles: #{Enum.product(fourPack)}")