-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsol_12.aes
99 lines (84 loc) · 2.62 KB
/
sol_12.aes
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
@compiler >= 4.2.0
include "List.aes"
contract Day12 =
record vec = {x : int, y : int, z : int}
record planet = { x : int, v : int }
record system = { p1 : planet, p2 : planet, p3 : planet, p4 : planet }
entrypoint solve_2() =
let data = input()
let p_x = periodicity([ p.x | p <- data ])
let p_y = periodicity([ p.y | p <- data ])
let p_z = periodicity([ p.z | p <- data ])
let a = (p_x * p_y) / gcd(p_x, p_y)
(a * p_z) / gcd(a, p_z)
entrypoint periodicity([x1, x2, x3, x4]) =
let s = {p1 = {x = x1, v = 0},
p2 = {x = x2, v = 0},
p3 = {x = x3, v = 0},
p4 = {x = x4, v = 0}}
pdc_p(0, s, {})
function pdc_p(step, s, m) =
if(Map.member(s, m)) step
else
let m' = m{[s] = ()}
let x1 = s.p1.x
let x2 = s.p2.x
let x3 = s.p3.x
let x4 = s.p4.x
let s' = { p1 = upd_p(s.p1, x2, x3, x4),
p2 = upd_p(s.p2, x3, x4, x1),
p3 = upd_p(s.p3, x4, x1, x2),
p4 = upd_p(s.p4, x1, x2, x3) }
pdc_p(step + 1, s', m')
function upd_p(p, x1, x2, x3) =
let delta(x) =
if(p.x > x) -1
elif(p.x < x) 1
else 0
let v = p.v + delta(x1) + delta(x2) + delta(x3)
{x = p.x + v, v = v}
function
gcd : (int, int) => int
gcd(a, 0) = a
gcd(a, b) = gcd(b, a mod b)
type moon = vec * vec
entrypoint solve_1() =
let v0 = {x = 0, y = 0, z = 0}
let ms = steps(1000, [ (p, v0) | p <- input() ])
(energy(ms), ms)
function steps(n, ms) =
if(n == 0) ms
else steps(n - 1, [step(m, ms) | m <- ms])
function
step : (moon, list(moon)) => moon
step((p, v), []) = ({x = p.x + v.x, y = p.y + v.y, z = p.z + v.z }, v)
step(m, m' :: ms) = step(update_vel(m, m'), ms)
function update_vel((p, v), (p2, _)) =
let upd(a, b, c) =
if(a > b) c - 1
elif(a < b) c + 1
else c
(p, { x = upd(p.x, p2.x, v.x),
y = upd(p.y, p2.y, v.y),
z = upd(p.z, p2.z, v.z) })
function energy(ms : list(moon)) =
let v_en(v) = abs(v.x) + abs(v.y) + abs(v.z)
let es = [v_en(p) * v_en(v) | (p, v) <- ms ]
List.foldl((a, b) => a + b, 0, es)
function abs(x) =
if(x < 0) -x else x
function input0() =
[{x = -1, y = 0, z = 2},
{x = 2, y = -10, z = -7},
{x = 4, y = -8, z = 8},
{x = 3, y = 5, z = -1}]
function input1() =
[{x = -8, y = -10, z = 0},
{x = 5, y = 5, z = 10},
{x = 2, y = -7, z = 3},
{x = 9, y = -8, z = -3}]
function input() =
[{x = 1, y = 2, z = -9},
{x = -1, y = -9, z = -4},
{x = 17, y = 6, z = 8},
{x = 12, y = 4, z = 2}]