aboutsummaryrefslogtreecommitdiff
path: root/2016/src/day25.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2016/src/day25.cpp')
-rw-r--r--2016/src/day25.cpp210
1 files changed, 210 insertions, 0 deletions
diff --git a/2016/src/day25.cpp b/2016/src/day25.cpp
new file mode 100644
index 0000000..ba3ad04
--- /dev/null
+++ b/2016/src/day25.cpp
@@ -0,0 +1,210 @@
1#include <filesystem>
2#include <fstream>
3#include <iostream>
4#include <map>
5#include <optional>
6#include <sstream>
7#include <string>
8#include <utility>
9#include <vector>
10
11using namespace std;
12
13namespace {
14
15enum class OpCode : uint8_t {
16 CPY,
17 INC,
18 DEC,
19 JNZ,
20 OUT,
21};
22
23using memory_type = map<char, int>;
24
25struct Argument {
26 explicit Argument(string value)
27 : value{ std::move(value) }
28 {
29 }
30
31 [[nodiscard]]
32 int eval(const memory_type& memory) const
33 {
34 const auto chr = value.at(0);
35
36 if ( chr >= 'a' && chr <= 'z' ) {
37 return memory.at(chr);
38 }
39 else {
40 return stoi(value);
41 }
42 }
43
44 [[nodiscard]]
45 char reg() const
46 {
47 if ( !is_reg() ) {
48 throw runtime_error("invalid register access! "s + value);
49 }
50
51 return value.at(0);
52 }
53
54 [[nodiscard]]
55 bool is_reg() const
56 {
57 const auto chr = value.at(0);
58
59 return chr >= 'a' && chr <= 'z';
60 }
61
62 string value;
63};
64
65struct Instruction {
66 Instruction(OpCode opCode, const Argument& x)
67 : opCode{ opCode }
68 , x{ x }
69 {
70 }
71
72 Instruction(OpCode opCode, const Argument& x, const Argument& y)
73 : opCode{ opCode }
74 , x{ x }
75 , y{ y }
76 {
77 }
78
79 OpCode opCode;
80 optional<Argument> x;
81 optional<Argument> y;
82};
83
84vector<string>
85split_words(const string& line, char sep = ' ')
86{
87 vector<string> words;
88 stringstream strm{ line };
89
90 for ( string word; getline(strm, word, sep); ) {
91 words.emplace_back(word);
92 }
93
94 return words;
95}
96
97vector<Instruction>
98read_file(const filesystem::path& filename)
99{
100 ifstream input{ filename };
101
102 vector<Instruction> instructions;
103
104 for ( string line; getline(input, line); ) {
105 const auto words = split_words(line);
106
107 if ( words.at(0) == "cpy" ) {
108 instructions.emplace_back(OpCode::CPY, Argument(words.at(1)), Argument(words.at(2)));
109 }
110 else if ( words.at(0) == "inc" ) {
111 instructions.emplace_back(OpCode::INC, Argument(words.at(1)));
112 }
113 else if ( words.at(0) == "dec" ) {
114 instructions.emplace_back(OpCode::DEC, Argument(words.at(1)));
115 }
116 else if ( words.at(0) == "jnz" ) {
117 instructions.emplace_back(OpCode::JNZ, Argument(words.at(1)), Argument(words.at(2)));
118 }
119 else if ( words.at(0) == "out" ) {
120 instructions.emplace_back(OpCode::OUT, Argument(words.at(1)));
121 }
122 else {
123 cerr << "unknown opcode..." << '\n';
124 }
125 }
126
127 return instructions;
128}
129
130#define JIT
131
132string
133execute(memory_type& memory, vector<Instruction> instructions)
134{
135 string result;
136
137 for ( size_t ip = 0; ip < instructions.size(); ) {
138 const auto& instruction = instructions.at(ip);
139
140 // cout << "#" << ip << " - " << memory['a'] << ", " << memory['b'] << ", " << memory['c'] << ", " << memory['d'] << ": " << (int) instruction.opCode << '\n';
141
142 switch ( instruction.opCode ) {
143 using enum OpCode;
144 case CPY:
145 memory[instruction.y->reg()] = instruction.x->eval(memory);
146 ++ip;
147 break;
148 case INC:
149 memory[instruction.x->reg()]++;
150 ++ip;
151 break;
152 case DEC:
153 memory[instruction.x->reg()]--;
154 ++ip;
155 break;
156 case JNZ:
157 if ( instruction.x->eval(memory) != 0 ) {
158 ip += static_cast<size_t>(instruction.y->eval(memory));
159 }
160 else {
161 ++ip;
162 }
163 break;
164 case OUT:
165 result += to_string(instruction.x->eval(memory));
166 if ( result.size() >= 20 ) {
167 ip = instructions.size();
168 }
169 else {
170 ++ip;
171 }
172 }
173 }
174
175 return result;
176}
177
178void
179part1(const vector<Instruction>& instructions)
180{
181 for ( int seed = 0;; ++seed ) {
182 map<char, int> memory;
183
184 memory['a'] = seed;
185 memory['b'] = 0;
186 memory['c'] = 0;
187 memory['d'] = 0;
188
189 auto result = execute(memory, instructions);
190
191 if ( result == "01010101010101010101" ) {
192 cout << "Part1: " << seed << '\n';
193 return;
194 }
195 }
196}
197
198} // namespace
199
200int
201main()
202{
203 const auto instructions = read_file("data/day25.txt");
204 try {
205 part1(instructions);
206 }
207 catch ( exception& e ) {
208 cerr << e.what() << '\n';
209 }
210}