aboutsummaryrefslogtreecommitdiff
path: root/2017/src/day16.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2017/src/day16.cpp')
-rw-r--r--2017/src/day16.cpp174
1 files changed, 174 insertions, 0 deletions
diff --git a/2017/src/day16.cpp b/2017/src/day16.cpp
new file mode 100644
index 0000000..ea048bb
--- /dev/null
+++ b/2017/src/day16.cpp
@@ -0,0 +1,174 @@
1#include <algorithm>
2#include <filesystem>
3#include <fstream>
4#include <iostream>
5#include <map>
6#include <sstream>
7#include <string>
8#include <vector>
9
10using namespace std;
11
12namespace {
13
14vector<string>
15read_line(const filesystem::path& filename)
16{
17 ifstream file{ filename };
18 vector<string> result;
19
20 for ( string line; getline(file, line, ','); ) {
21 result.emplace_back(line);
22 }
23 return result;
24}
25
26vector<string>
27split(const string& line, char sep = '/')
28{
29 stringstream strm{ line };
30 vector<string> result;
31
32 for ( string line; getline(strm, line, sep); ) {
33 result.emplace_back(line);
34 }
35 return result;
36}
37
38void
39spin(string& line, size_t n)
40{
41 ranges::reverse(line);
42 reverse(line.begin(), line.begin() + static_cast<string::difference_type>(n));
43 reverse(line.begin() + static_cast<string::difference_type>(n), line.end());
44}
45
46void
47exchange(string& line, size_t a, size_t b)
48{
49 swap(line.at(a), line.at(b));
50}
51
52void
53partner(string& line, char a, char b)
54{
55 auto iter_a = ranges::find(line, a);
56 auto iter_b = ranges::find(line, b);
57 iter_swap(iter_a, iter_b);
58}
59
60void
61dance(const vector<string>& instructions, string& line)
62{
63 for ( const auto& instr: instructions ) {
64 auto values = split(instr.substr(1));
65
66 switch ( instr.at(0) ) {
67 case 's':
68 spin(line, stoul(values.at(0)));
69 break;
70 case 'x':
71 exchange(line, stoul(values.at(0)), stoul(values.at(1)));
72 break;
73 case 'p':
74 partner(line, values.at(0).at(0), values.at(1).at(0));
75 break;
76 default:
77 throw runtime_error("inknown command");
78 }
79 }
80}
81
82void
83part1(const vector<string>& instructions, string line)
84{
85 dance(instructions, line);
86 cout << "Part1: " << line << '\n';
87}
88
89#if defined(WASTE_TIME)
90void
91part2_bf(const vector<string>& instructions, string line)
92{
93 for ( long round = 0; round != 1'000'000'000; ++round ) {
94 dance(instructions, line);
95 }
96
97 cout << "Part2-BF: " << line << '\n';
98}
99#endif
100
101void
102part2(const vector<string>& instructions, string line)
103{
104 map<string, size_t> seen;
105 vector<string> history;
106
107 size_t cycle_start = 0;
108 size_t cycle_length = 0;
109
110 for ( size_t round = 0;; ++round ) {
111 if ( seen.contains(line) ) {
112 cycle_start = seen.at(line);
113 cycle_length = round - cycle_start;
114 break;
115 }
116
117 seen[line] = round;
118 history.emplace_back(line);
119
120 dance(instructions, line);
121 }
122
123 const size_t total_rounds = 1'000'000'000L;
124 const size_t remaining = (total_rounds - cycle_start) % cycle_length;
125
126 cout << "Part2: " << history.at(cycle_start + remaining) << '\n';
127}
128
129void
130part2_alt(const vector<string>& instructions, const string& line)
131{
132 auto slow = line;
133 dance(instructions, slow);
134
135 auto fast = line;
136 dance(instructions, fast);
137 dance(instructions, fast);
138
139 // find cycle
140 while ( slow != fast ) {
141 dance(instructions, slow);
142 dance(instructions, fast);
143 dance(instructions, fast);
144 }
145
146 // find cycle length
147 size_t cycle_length = 1;
148 dance(instructions, slow);
149 while ( slow != fast ) {
150 dance(instructions, slow);
151 ++cycle_length;
152 }
153
154 // process remaining rounds
155 const size_t total_rounds = 1'000'000'000L;
156 for ( auto remaining = total_rounds % cycle_length; remaining-- > 0; ) {
157 dance(instructions, slow);
158 }
159
160 cout << "Part2-Alt: " << slow << '\n';
161}
162
163} // namespace
164
165int
166main()
167{
168 auto instructions = read_line("data/day16.txt");
169 auto line = "abcdefghijklmnop"s;
170
171 part1(instructions, line);
172 part2(instructions, line);
173 part2_alt(instructions, line);
174}