From 756f22d58bb198b8f34589c112e1003614ccdcd6 Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Sun, 2 Nov 2025 21:41:58 +0100 Subject: aoc 2017, days 1-20 --- 2017/src/day18.cpp | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 2017/src/day18.cpp (limited to '2017/src/day18.cpp') diff --git a/2017/src/day18.cpp b/2017/src/day18.cpp new file mode 100644 index 0000000..bfdd7e3 --- /dev/null +++ b/2017/src/day18.cpp @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace { + +template +struct CPU { + [[nodiscard]] + T get(const string& ref) + { + T value{}; + auto [ptr, ec] = from_chars(ref.data(), ref.data() + ref.size(), value); + + if ( ec == errc() ) { + return value; + } + + return memory[ref]; + } + + void set(const string& ref, T value) + { + memory[ref] = value; + } + + void add(const string& ref, T value) + { + memory[ref] += value; + } + + void mul(const string& ref, T value) + { + memory[ref] *= value; + } + + void mod(const string& ref, T value) + { + memory[ref] %= value; + } + + T execute(const vector>& code) + { + long played_sound{}; + + for ( size_t ip = 0; ip < code.size(); ++ip ) { + const auto& line = code.at(ip); + const auto& opcode = line.at(0); + + if ( opcode == "snd" ) { + played_sound = get(line.at(1)); + } + else if ( opcode == "rcv" ) { + auto value = get(line.at(1)); + if ( value != 0 ) { + return played_sound; + } + } + else if ( opcode == "set" ) { + set(line.at(1), get(line.at(2))); + } + else if ( opcode == "add" ) { + add(line.at(1), get(line.at(2))); + } + else if ( opcode == "mul" ) { + mul(line.at(1), get(line.at(2))); + } + else if ( opcode == "mod" ) { + mod(line.at(1), get(line.at(2))); + } + else if ( opcode == "jgz" ) { + auto value = get(line.at(1)); + if ( value > 0 ) { + auto offset = get(line.at(2)); + ip += static_cast(offset - 1); + } + } + else { + cerr << "unknown opcode: " << opcode << '\n'; + return -1; + } + } + return -1; + } + + map memory; +}; + +template +struct CPU2 { + CPU2(queue& in, queue& out) + : in{ in } + , out{ out } + { + } + + [[nodiscard]] + T get(const string& ref) + { + T value{}; + auto [ptr, ec] = from_chars(ref.data(), ref.data() + ref.size(), value); + + if ( ec == errc() ) { + return value; + } + + return memory[ref]; + } + + void set(const string& ref, T value) + { + memory[ref] = value; + } + + void add(const string& ref, T value) + { + memory[ref] += value; + } + + void mul(const string& ref, T value) + { + memory[ref] *= value; + } + + void mod(const string& ref, T value) + { + memory[ref] %= value; + } + + bool step(const vector>& code) + { + if ( ip >= code.size() ) { + return false; + } + + const auto& line = code.at(ip); + const auto& opcode = line.at(0); + + if ( opcode == "snd" ) { + out.push(get(line.at(1))); + ++send_count; + } + else if ( opcode == "rcv" ) { + if ( in.empty() ) { + waiting = true; + return true; + } + else { + auto value = in.front(); + in.pop(); + set(line.at(1), value); + waiting = false; + } + } + else if ( opcode == "set" ) { + set(line.at(1), get(line.at(2))); + } + else if ( opcode == "add" ) { + add(line.at(1), get(line.at(2))); + } + else if ( opcode == "mul" ) { + mul(line.at(1), get(line.at(2))); + } + else if ( opcode == "mod" ) { + mod(line.at(1), get(line.at(2))); + } + else if ( opcode == "jgz" ) { + auto value = get(line.at(1)); + if ( value > 0 ) { + auto offset = get(line.at(2)); + ip += static_cast(offset); + return true; + } + } + else { + cerr << "unknown opcode: " << opcode << '\n'; + return false; + } + + ++ip; + + return true; + } + + size_t ip{}; + queue& in; + queue& out; + bool waiting{ false }; + T send_count{}; + map memory; +}; + +vector +split(const string& line) +{ + stringstream strm{ line }; + vector data; + + for ( string line; strm >> line; ) { + data.emplace_back(line); + } + + return data; +} + +vector> +read_file(const filesystem::path& filename) +{ + ifstream file{ filename }; + vector> data; + + for ( string line; getline(file, line); ) { + const auto parts = split(line); + data.emplace_back(parts); + } + + return data; +} + +void +part1(const vector>& code) +{ + CPU cpu{}; + + cout << "Part1: " << cpu.execute(code) << '\n'; +} + +void +part2(const vector>& code) +{ + queue queue1; + queue queue2; + CPU2 cpu1{ queue1, queue2 }; + CPU2 cpu2{ queue2, queue1 }; + + cpu1.set("p", 0); + cpu2.set("p", 1); + + for ( ;; ) { + auto cpu1_running = cpu1.step(code); + auto cpu2_running = cpu2.step(code); + + if ( (cpu1.waiting || !cpu1_running) && (cpu2.waiting || !cpu2_running) ) { + break; + } + } + cout << "Part2: " << cpu2.send_count << '\n'; +} + +} // namespace + +int +main() +{ + auto instr = read_file("data/day18.txt"); + part1(instr); + part2(instr); +} -- cgit v1.3