-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathDay12.re
110 lines (94 loc) · 2.6 KB
/
Day12.re
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
open Tablecloth;
module Coordinates = {
let make = ((coords, _)) => coords;
};
module Velocity = {
let make = (x, y) => {
switch (x, y) {
| (x, y) when x === y => 0
| (x, y) when y > x => 1
| _ => (-1)
};
};
};
module Energy = {
let make = ((x, y, z)) => abs(x) + abs(y) + abs(z);
};
module Step = {
let make = moons =>
moons
|> List.map(~f=(((x, y, z), v)) => {
let (vx, vy, vz) =
moons
|> List.foldl(
~init=v,
~f=(moon, (ax, ay, az)) => {
let (xx, yy, zz) = Coordinates.make(moon);
(
ax + Velocity.make(x, xx),
ay + Velocity.make(y, yy),
az + Velocity.make(z, zz),
);
},
);
((x + vx, y + vy, z + vz), (vx, vy, vz));
});
};
module PartOne = {
let rec make = (moons, ~iterations) => {
switch (iterations) {
| 0 =>
moons
|> List.map(~f=((potential, kinetic)) => {
Energy.make(potential) * Energy.make(kinetic)
})
|> List.foldl(~init=0, ~f=(+))
| _ => make(Step.make(moons), ~iterations=iterations - 1)
};
};
};
module PartTwo = {
module Hash = {
let make = values => {
values
|> List.foldl(~init="", ~f=((x, v), acc) => {
acc ++ (x |> string_of_int) ++ (v |> string_of_int)
});
};
};
module Steps = {
module Count = {
let rec make = (values, ~seen, ~steps=1, ()) => {
let nextValues =
values
|> List.map(~f=((x, v)) => {
let vx =
values
|> List.foldl(~init=v, ~f=((y, _), acc) =>
acc + Velocity.make(x, y)
);
(x + vx, vx);
});
let nextHash = Hash.make(nextValues);
switch (seen |> StrSet.has(~value=nextHash)) {
| false =>
let seen = seen |> StrSet.add(~value=nextHash);
make(nextValues, ~seen, ~steps=steps + 1, ());
| true => steps
};
};
};
let make = values => {
let seen = StrSet.empty;
let hash = Hash.make(values);
let start = seen |> StrSet.add(~value=hash);
Count.make(values, ~seen=start, ());
};
};
let make = moons => {
let x = moons |> List.map(~f=(((x, _, _), _)) => (x, 0)) |> Steps.make;
let y = moons |> List.map(~f=(((_, y, _), _)) => (y, 0)) |> Steps.make;
let z = moons |> List.map(~f=(((_, _, z), _)) => (z, 0)) |> Steps.make;
Mathematics.LeastCommonMultiple.fromList([x, y, z]);
};
};