aboutsummaryrefslogtreecommitdiff
path: root/2016
diff options
context:
space:
mode:
Diffstat (limited to '2016')
-rw-r--r--2016/src/day16.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/2016/src/day16.cpp b/2016/src/day16.cpp
new file mode 100644
index 0000000..7d24dd3
--- /dev/null
+++ b/2016/src/day16.cpp
@@ -0,0 +1,84 @@
1#include <iostream>
2#include <string_view>
3
4using namespace std;
5
6namespace {
7
8size_t
9smallest_dragon_length(string_view start_bits, size_t disc_size)
10{
11 auto length = start_bits.size();
12 while ( length < disc_size ) {
13 length = 2 * length + 1;
14 }
15 return length;
16}
17
18char
19bit_at(size_t pos, size_t total_length, string_view start_bits)
20{
21 size_t inversions = 0;
22
23 auto invert_if_needed = [&](char chr) {
24 if ( (inversions % 2) == 1 ) {
25 return (chr == '0') ? '1' : '0';
26 }
27 else {
28 return chr;
29 }
30 };
31
32 while ( total_length > start_bits.size() ) {
33 auto prev_length = (total_length - 1) / 2;
34
35 if ( pos == prev_length ) {
36 return invert_if_needed('0');
37 }
38 else if ( pos > prev_length ) {
39 pos = prev_length - 1 - (pos - prev_length - 1);
40 inversions++;
41 total_length = prev_length;
42 }
43 else {
44 total_length = prev_length;
45 }
46 }
47
48 auto bit = start_bits[pos];
49
50 return invert_if_needed(bit);
51}
52
53void
54checksum(string_view start_bits, size_t disc_size)
55{
56 auto data_length = smallest_dragon_length(start_bits, disc_size);
57
58 string bits;
59 for ( size_t i = 0; i != disc_size; ++i ) {
60 bits += bit_at(i, data_length, start_bits);
61 }
62
63 while ( bits.size() % 2 == 0 ) {
64 string new_bits;
65
66 for ( size_t i = 0; i != bits.size(); i += 2 ) {
67 new_bits += (bits[i] == bits[i + 1]) ? '1' : '0';
68 }
69
70 bits = std::move(new_bits);
71 }
72
73 cout << bits << '\n';
74}
75
76} // namespace
77
78int
79main()
80{
81 // checksum("10000", 20);
82 checksum("00111101111101000", 272);
83 checksum("00111101111101000", 35651584);
84}