-
Notifications
You must be signed in to change notification settings - Fork 1
/
day15.c3
140 lines (132 loc) · 3.3 KB
/
day15.c3
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
140
/*
* Advent of Code 2023 day 15
*/
import std::io;
import std::time;
import std::collections::list;
fn void main()
{
io::printn("Advent of code, day 15.");
@pool()
{
// Load the whole data in a single sweep.
char[] data = file::load_temp("day15.txt")!!;
// Simple benchmarking with Clock, "mark" returns the last duration and resets the clock
Clock c = clock::now();
io::printfn("* Sum part 1: %d - completed in %s", part1(data), c.mark());
io::printfn("* Sum part 2: %d - completed in %s", part2(data), c.mark());
};
}
fn long part1(char[] data)
{
long sum = 0;
// Sum the current hash in 'current'
long current = 0;
foreach (c : data)
{
// If we reach a new number, add 'current' and
// and start a new hash calculation.
if (c == ',')
{
sum += current;
current = 0;
continue;
}
// Perform the hash calculation.
current = ((current + c) * 17) & 0xFF;
}
// Add any pending "current" to the sum.
return sum + current;
}
struct Lens
{
char[] name;
int focal_length;
}
def LensList = List(<Lens>);
// Part2 is essentially implementing a hash map.
fn long part2(char[] data)
{
// Create our fixed set of boxes with Lists
// we could also do this with linked lists.
LensList[256] boxes;
foreach (&box : boxes) box.init_temp();
// Again we just walk through the data without
// separating it, so we need to keep track
// of what the "first" character in the label is.
int first = 0;
long current = 0;
for OUTER: (int i = 0; i < data.len; i++)
{
// Switch over the character
char c = data[i];
switch (c)
{
case ',':
// A comma, that means we update what the first
// character is (the next one after this)
// we also reset the hash (although we could do
// this elsewhere too)
first = i + 1;
current = 0;
continue;
case '-':
// This is a removal. We first grab the name
// as a slice:
char[] name = data[first..i - 1];
// We then loop over all of the lenses in the
// current box.
foreach (j, &lens : boxes[current])
{
// If we match the name, we remove it
// since we use a List, this automatically
// fixes the ordering.
// Note that there can only be a single entry
// with the same name, so if we get a match
// we're done.
if (lens.name == name)
{
boxes[current].remove_at(j);
break;
}
}
case '=':
// Get the name of the lens to add
char[] name = data[first..i - 1];
// Now skip forward and grab the focal length
i++;
int focal_length = data[i] - '0';
// We first try to see if we have it already
foreach (j, &lens : boxes[current])
{
if (lens.name == name)
{
// If we do, we only need to update the
// focal length
lens.focal_length = focal_length;
continue OUTER;
}
}
// Otherwise, we append the new lens at the end of the
// list.
boxes[current].push({ name, focal_length });
case 'a'..'z':
// For a-z this is a name
current = ((current + c) * 17) & 0xFF;
default:
// We should not get any other matches, so mark this as
// unreachable.
unreachable();
}
}
// Now, we're done, so just sum up the "focusing power"
long sum = 0;
foreach (i, &box : boxes)
{
foreach (j, &lens : *box)
{
sum += (i + 1) * (j + 1) * lens.focal_length;
}
}
return sum;
}