1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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)}")
|