-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay10.roc
139 lines (110 loc) · 3.17 KB
/
Day10.roc
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
interface Day10 exposes [ output ] imports [ ListExtra, ListZip, TestUtil ]
output : List I64 -> List (List I64)
output = \puzzleInput ->
testNumbers1 = testInput1 |> TestUtil.ints |> ListExtra.quicksort
testNumbers2 = testInput2 |> TestUtil.ints |> ListExtra.quicksort
puzzleNumbers = puzzleInput |> TestUtil.ints |> ListExtra.quicksort
[ TestUtil.verify 10 1 1 (differences testNumbers1 ) 35
, TestUtil.verify 10 1 2 (differences testNumbers2 ) 220
, TestUtil.show 10 1 (differences puzzleNumbers)
, TestUtil.verify 10 2 1 (arrangements testNumbers1 ) 8
, TestUtil.verify 10 2 2 (arrangements testNumbers2 ) 19208
, TestUtil.show 10 2 (arrangements puzzleNumbers)
]
# first part
differences : List I64 -> I64
differences = \input ->
initial = { last: 0, ones: 0, threes: 1 }
final = List.walk input diffWalker initial
final.ones * final.threes
DiffAcc : { last : I64, ones : I64, threes : I64 }
diffWalker : I64, DiffAcc -> DiffAcc
diffWalker = \val, acc ->
when val - acc.last is
1 -> { acc & last: val, ones: acc.ones + 1 }
3 -> { acc & last: val, threes: acc.threes + 1 }
_ -> { acc & last: val }
# second part
arrangements : List I64 -> I64
arrangements = \input ->
initial = { last: 0, count: 0, tribs: [ 1, 1, 2 ], result: 1 }
last = List.walk input arrWalker initial
final = arrWalkerHelper 0 3 last
final.result
ArrAcc : { last : I64, count : I64, tribs: List I64, result : I64 }
arrWalker : I64, ArrAcc -> ArrAcc
arrWalker = \val, acc ->
diff = val - acc.last
arrWalkerHelper val diff acc
arrWalkerHelper : I64, I64, ArrAcc -> ArrAcc
arrWalkerHelper = \val, diff, acc ->
if diff == 1 then
{ acc & last: val, count: acc.count + 1 }
else if acc.count > 1 then
newTribs = ensureTribs acc.tribs acc.count
factor = (ListZip.newAt newTribs acc.count 0).val
{ acc & last: val, count: 0, tribs: newTribs, result: acc.result * factor }
else
{ acc & last: val, count: 0 }
# Tribonacci numbers
ensureTribs : List I64, I64 -> List I64
ensureTribs = \tribs, idx ->
len = List.len tribs
if len > idx then
tribs
else
zip0 = ListZip.newAtLast tribs 0
zip1 = ListZip.backward zip0 tribs
zip2 = ListZip.backward zip1 tribs
nextTrib = zip0.val + zip1.val + zip2.val
newTribs = List.append tribs nextTrib
ensureTribs newTribs idx
# test data
testInput1 : List I64
testInput1 =
[ 49, 54, 10
, 49, 48, 10
, 49, 53, 10
, 53, 10
, 49, 10
, 49, 49, 10
, 55, 10
, 49, 57, 10
, 54, 10
, 49, 50, 10
, 52, 10
]
testInput2 : List I64
testInput2 =
[ 50, 56, 10
, 51, 51, 10
, 49, 56, 10
, 52, 50, 10
, 51, 49, 10
, 49, 52, 10
, 52, 54, 10
, 50, 48, 10
, 52, 56, 10
, 52, 55, 10
, 50, 52, 10
, 50, 51, 10
, 52, 57, 10
, 52, 53, 10
, 49, 57, 10
, 51, 56, 10
, 51, 57, 10
, 49, 49, 10
, 49, 10
, 51, 50, 10
, 50, 53, 10
, 51, 53, 10
, 56, 10
, 49, 55, 10
, 55, 10
, 57, 10
, 52, 10
, 50, 10
, 51, 52, 10
, 49, 48, 10
, 51, 10
]