aboutsummaryrefslogtreecommitdiff
path: root/2017/src/day14.cpp
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2025-11-02 21:41:58 +0100
committerThomas Schmucker <ts@its1.de>2025-11-02 21:41:58 +0100
commit756f22d58bb198b8f34589c112e1003614ccdcd6 (patch)
tree4cdeba335f1ea67f7ead9e9f763ba1c3c206fc4d /2017/src/day14.cpp
parentfcbb722bd4c5ca2bd34a7cf9c0ba48f2f955da13 (diff)
downloadadvent-of-code-756f22d58bb198b8f34589c112e1003614ccdcd6.tar.gz
advent-of-code-756f22d58bb198b8f34589c112e1003614ccdcd6.tar.bz2
advent-of-code-756f22d58bb198b8f34589c112e1003614ccdcd6.zip
aoc 2017, days 1-20
Diffstat (limited to '2017/src/day14.cpp')
-rw-r--r--2017/src/day14.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/2017/src/day14.cpp b/2017/src/day14.cpp
new file mode 100644
index 0000000..d226d46
--- /dev/null
+++ b/2017/src/day14.cpp
@@ -0,0 +1,146 @@
1#include <array>
2#include <iostream>
3#include <numeric>
4#include <queue>
5#include <set>
6#include <string>
7#include <vector>
8
9using namespace std;
10
11namespace {
12
13vector<unsigned>
14gen_data(size_t len)
15{
16 vector<unsigned> data(len);
17 iota(data.begin(), data.end(), 0UL);
18 return data;
19}
20
21void
22reverse(vector<unsigned>& data, size_t start, size_t len)
23{
24 auto end = start + len;
25
26 while ( start < end ) {
27 swap(data.at(start++ % data.size()), data.at(--end % data.size()));
28 }
29}
30
31void
32hash64(vector<unsigned>& data, const vector<size_t>& lengths)
33{
34 size_t pos = 0;
35 size_t skip = 0;
36 for ( size_t i = 0; i != 64; ++i ) {
37 for ( auto length: lengths ) {
38 reverse(data, pos, length);
39 pos += length + skip;
40 ++skip;
41 }
42 }
43}
44
45vector<uint8_t>
46knothash(string line)
47{
48 line += char(17);
49 line += char(31);
50 line += char(73);
51 line += char(47);
52 line += char(23);
53
54 vector<size_t> lengths;
55 for ( const auto byte: line ) {
56 lengths.emplace_back(static_cast<unsigned char>(byte));
57 }
58
59 auto data = gen_data(256);
60 hash64(data, lengths);
61
62 vector<uint8_t> result;
63 for ( size_t i = 0; i != 256; i += 16 ) {
64 size_t value = 0;
65 for ( size_t j = 0; j != 16; ++j ) {
66 value ^= data.at(i + j);
67 }
68 result.emplace_back(value & 0xFF);
69 }
70 return result;
71}
72
73void
74part1(const string& line)
75{
76 int count = 0;
77 for ( int i = 0; i != 128; ++i ) {
78 auto result = knothash(line + "-"s + to_string(i));
79
80 for ( const auto value: result ) {
81 count += popcount(value);
82 }
83 }
84 cout << "Part1: " << count << '\n';
85}
86
87void
88part2(const string& line)
89{
90 set<tuple<size_t, size_t>> grid;
91
92 for ( size_t y = 0; y != 128; ++y ) {
93 auto result = knothash(line + "-"s + to_string(y));
94
95 for ( size_t x = 0; x != 128; ++x ) {
96 auto value = result.at(x / 8);
97 auto mask = 1u << (7 - (x % 8));
98
99 if ( (value & mask) != 0 ) {
100 grid.emplace(x, y);
101 }
102 }
103 }
104
105 int count = 0;
106
107 for ( size_t x = 0; x != 128; ++x ) {
108 for ( size_t y = 0; y != 128; ++y ) {
109 if ( !grid.contains({ x, y }) ) {
110 continue;
111 }
112
113 ++count;
114
115 queue<tuple<size_t, size_t>> queue;
116 queue.emplace(x, y);
117
118 while ( !queue.empty() ) {
119 auto pos = queue.front();
120 queue.pop();
121
122 grid.erase(pos);
123
124 static array<tuple<size_t, size_t>, 4> dirs{ make_tuple(-1, 0), make_tuple(1, 0), make_tuple(0, -1), make_tuple(0, 1) };
125
126 for ( const auto [dx, dy]: dirs ) {
127 const auto new_pos = make_tuple(dx + get<0>(pos), dy + get<1>(pos));
128 if ( grid.contains(new_pos) ) {
129 queue.emplace(new_pos);
130 }
131 }
132 }
133 }
134 }
135 cout << "Part2: " << count << '\n';
136}
137
138} // namespace
139
140int
141main()
142{
143 const string input = "ffayrhll";
144 part1(input);
145 part2(input);
146}