9
9
#include < stack>
10
10
#include < queue>
11
11
12
- struct Node {
13
- Node* left;
14
- Node* right ;
15
- int value ;
16
- int steps_to_split ;
12
+ struct Node
13
+ {
14
+ Node *left ;
15
+ Node *right ;
16
+ uint64_t value ;
17
17
};
18
18
19
19
struct Data
20
20
{
21
21
std::vector<int > stones;
22
22
};
23
23
24
- int part1 (const Data &data)
24
+ Node *get_node (uint64_t new_value, std::map<uint64_t , std::unique_ptr<Node>> &splits)
25
+ {
26
+ if (!splits.contains (new_value))
27
+ {
28
+ splits[new_value] = std::make_unique<Node>(Node{.left = nullptr , .right = nullptr , .value = new_value});
29
+ }
30
+ return splits[new_value].get ();
31
+ }
32
+
33
+ uint64_t part1 (const Data &data)
25
34
{
26
- std::map<int , std::unique_ptr<Node>> splits;
27
- int sum = 0 ;
35
+ std::map<uint64_t , std::unique_ptr<Node>> splits;
36
+ uint64_t sum = 0 ;
28
37
29
38
for (auto &stone : data.stones )
30
39
{
31
40
// stone value, depth
32
- std::queue<std::pair<int , int >> q;
41
+ std::queue<std::pair<uint64_t , uint64_t >> q;
33
42
q.push ({stone, 0 });
34
43
sum += 1 ;
35
- int n_steps = 6 ;
44
+ uint64_t n_steps = 25 ;
36
45
37
46
while (!q.empty ())
38
47
{
39
48
auto val = q.front ();
40
- Node* cur = nullptr ;
49
+ Node * cur = get_node (val. first , splits) ;
41
50
42
- if (!splits.contains (val.first )) {
43
- splits[val.first ] = std::make_unique<Node>(Node{.left = nullptr , .right = nullptr , .value = val.first , .steps_to_split = 0 });
44
- }
45
- cur = splits[val.first ].get ();
46
51
47
52
for (size_t blink = val.second ; blink < n_steps; ++blink)
48
53
{
49
- if (splits. contains (val. first ) && cur->left != nullptr )
54
+ while ( cur->left != nullptr && blink < n_steps )
50
55
{
51
- cur = splits[val.first ].get ();
52
- if (cur->left != nullptr && cur->right != nullptr )
56
+ if (cur->right != nullptr )
53
57
{
54
- if (cur->steps_to_split + blink > n_steps)
55
- {
56
- break ;
57
- }
58
- sum += 1 ;
59
- blink += cur->steps_to_split ;
60
- cur = cur->left ;
61
- val.first = cur->value ;
62
- continue ;
58
+ ++sum;
59
+ q.push ({cur->right ->value , blink + 1 });
63
60
}
61
+ ++blink;
62
+ cur = cur->left ;
64
63
}
65
-
66
- int num_digits = std::floor (std::log10 (val.first )) + 1 ;
67
- if (val.first == 0 )
64
+ if (blink >= n_steps)
65
+ break ;
66
+ uint64_t num_digits = std::floor (std::log10 (cur->value )) + 1 ;
67
+ if (cur->value == 0 )
68
68
{
69
- val.first = 1 ;
70
- cur->steps_to_split += 1 ;
69
+ Node *next = get_node (1 , splits);
70
+ cur->left = next;
71
+ cur = cur->left ;
71
72
}
72
73
else if (num_digits % 2 == 0 )
73
74
{
74
- int right_half = val. first % int (std::pow (10 , num_digits / 2 ));
75
- val. first /= std::pow (10 , num_digits / 2 );
75
+ uint64_t right_half = cur-> value % uint64_t (std::pow (10 , num_digits / 2 ));
76
+ uint64_t left_half = cur-> value / std::pow (10 , num_digits / 2 );
76
77
sum += 1 ;
77
- if (!splits.contains (right_half))
78
- {
79
- splits[right_half] = std::make_unique<Node>(Node{.left = nullptr , .right = nullptr , .value = right_half, .steps_to_split = 0 });
80
- }
81
- if (!splits.contains (val.first ))
82
- {
83
- splits[val.first ] = std::make_unique<Node>(Node{.left = nullptr , .right = nullptr , .value = val.first , .steps_to_split = 0 });
84
- }
85
- cur->left = splits[val.first ].get ();
86
- cur->right = splits[right_half].get ();
78
+ Node *left = get_node (left_half, splits);
79
+ Node *right = get_node (right_half, splits);
80
+ cur->left = left;
81
+ cur->right = right;
87
82
cur = cur->left ;
88
83
q.push ({right_half, blink + 1 });
89
84
}
90
85
else
91
86
{
92
- val.first *= 2024 ;
93
- cur->steps_to_split += 1 ;
87
+ Node *next = get_node (cur->value * 2024 , splits);
88
+ cur->left = next;
89
+ cur = cur->left ;
94
90
}
95
91
}
96
92
q.pop ();
@@ -137,7 +133,7 @@ BENCHMARK_DEFINE_F(BenchmarkFixture, Part1Benchmark)
137
133
{
138
134
for (auto _ : state)
139
135
{
140
- int s = part1 (data);
136
+ uint64_t s = part1 (data);
141
137
benchmark::DoNotOptimize (s);
142
138
}
143
139
}
@@ -159,7 +155,7 @@ int main(int argc, char **argv)
159
155
{
160
156
Data data = parse ();
161
157
162
- int answer1 = 0 ;
158
+ uint64_t answer1 = 0 ;
163
159
int answer2 = 0 ;
164
160
165
161
auto first = part1 (data);
0 commit comments