advent2024

Advent of Code 2024
git clone git://bsandro.tech/advent2024
Log | Files | Refs

commit cbc677f8e10ebdb7017d10d5cddcc76dd010bf7e
parent e819cc8bb54f51d1be2e65984da7bbbef204e79f
Author: bsandro <email@bsandro.tech>
Date:   Thu, 19 Dec 2024 21:40:57 +0200

Day 17 p2 fruitful attempts

Diffstat:
Mday17/main.cpp | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Aday17/test2.txt | 5+++++
2 files changed, 115 insertions(+), 37 deletions(-)

diff --git a/day17/main.cpp b/day17/main.cpp @@ -7,6 +7,9 @@ #include <tuple> #include <algorithm> #include <cmath> +#include <climits> +#include <thread> +#include <future> #include "utils.hpp" typedef std::vector<std::pair<int, int>> Data; @@ -16,11 +19,11 @@ public: // instruction pointer int ip = 0; // registers - int a = 0; - int b = 0; - int c = 0; + int64_t a = 0; + int64_t b = 0; + int64_t c = 0; // combo operand - int combo(int o) { + int64_t combo(int o) { if (o>=0&&o<=3) return o; if (o==4) return a; if (o==5) return b; @@ -29,21 +32,29 @@ public: return 0; } // opcodes 0-7 - int adv(int o) { a /= std::pow(2, combo(o)); return ++ip; } - int bxl(int o) { b ^= o; return ++ip; }; - int bst(int o) { b = combo(o) % 8; return ++ip; }; - int jnz(int o) { if (a==0) ip++; else ip=o; return ip; }; - int bxc(int o [[maybe_unused]]) { b ^= c; return ++ip; }; - int out(int o, std::stringstream &ss) { ss << (combo(o)%8) << ","; return ++ip; }; - int bdv(int o) { b = a/std::pow(2, combo(o)); return ++ip; }; - int cdv(int o) { c = a/std::pow(2, combo(o)); return ++ip; }; + int adv(int64_t o) { a /= std::pow(2, combo(o)); return ++ip; } + int bxl(int64_t o) { b ^= o; return ++ip; }; + int bst(int64_t o) { b = combo(o) % 8; return ++ip; }; + int jnz(int64_t o) { if (a==0) ip++; else ip=o; return ip; }; + int bxc(int64_t o [[maybe_unused]]) { b ^= c; return ++ip; }; + int out(int64_t o, std::stringstream &ss) { ss << (combo(o)%8) << ","; return ++ip; }; + int bdv(int64_t o) { b = a/std::pow(2, combo(o)); return ++ip; }; + int cdv(int64_t o) { c = a/std::pow(2, combo(o)); return ++ip; }; // main thing - int eval(int op, int o, std::stringstream &ss); + int eval(int op, int64_t o, std::stringstream &ss); std::string run(const Data &input); - void print() { std::printf("ip:%d,a:%d,b:%d,c:%d\n", ip, a, b, c); } + void reset(); + void print() { std::printf("ip:%d,a:%ld,b:%ld,c:%ld\n", ip, a, b, c); } }; -int Cpu::eval(int op, int o, std::stringstream &ss) { +void Cpu::reset() { + a = 0; + b = 0; + c = 0; + ip = 0; +} + +int Cpu::eval(int op, int64_t o, std::stringstream &ss) { switch (op) { case 0: return adv(o); case 1: return bxl(o); @@ -61,7 +72,26 @@ int Cpu::eval(int op, int o, std::stringstream &ss) { std::string Cpu::run(const Data &input) { std::stringstream ss; while (ip>=0&&ip<(int)input.size()) ip=eval(input[ip].first, input[ip].second, ss); - return ss.str(); + std::string out = ss.str(); + out.pop_back(); // to remove the trailing comma + return out; +} + +Data read_data(const std::string str) { + Data buf; + std::istringstream iss(str); + std::pair<int,int> instr; + int num = 0; + for (std::string sn; std::getline(iss, sn, ',');) { + if (num%2==0) { + instr.first = std::stoi(sn); + } else { + instr.second = std::stoi(sn); + buf.push_back(instr); + } + num++; + } + return buf; } std::tuple<Cpu, Data> read_file(const std::string &path) { @@ -75,24 +105,13 @@ std::tuple<Cpu, Data> read_file(const std::string &path) { std::string str; std::getline(ifs, str); if (!str.empty()) { - if (l==0) std::sscanf(str.c_str(), "Register A: %d", &cpu.a); - if (l==1) std::sscanf(str.c_str(), "Register B: %d", &cpu.b); - if (l==2) std::sscanf(str.c_str(), "Register C: %d", &cpu.c); + if (l==0) std::sscanf(str.c_str(), "Register A: %ld", &cpu.a); + if (l==1) std::sscanf(str.c_str(), "Register B: %ld", &cpu.b); + if (l==2) std::sscanf(str.c_str(), "Register C: %ld", &cpu.c); if (l==4) { char tmp[256] = {0}; std::sscanf(str.c_str(), "Program: %[^\n]", tmp); - std::istringstream iss(tmp); - std::pair<int,int> instr; - int num = 0; - for (std::string sn; std::getline(iss, sn, ',');) { - if (num%2==0) { - instr.first = std::stoi(sn); - } else { - instr.second = std::stoi(sn); - buf.push_back(instr); - } - num++; - } + buf = read_data(tmp); } } if (!ifs) break; @@ -101,14 +120,68 @@ std::tuple<Cpu, Data> read_file(const std::string &path) { } std::string part1(Cpu cpu [[ maybe_unused ]], Data input [[ maybe_unused ]]) { - //cpu.print(); - //for (auto [opcode, operand] : input) std::printf("[%d,%d]", opcode, operand); - return cpu.run(input); } -int64_t part2(Data &input [[ maybe_unused ]]) { - return 0; +int64_t part2(Cpu cpu, const Data input) { + for (int64_t i=0; i<INT64_MAX; ++i) { + cpu.reset(); + cpu.a = i; + Data derived = read_data(cpu.run(input)); + if (derived==input) return i; + } + return -1; +} + +int64_t part2_threaded(Cpu cpu [[maybe_unused]], Data input [[ maybe_unused ]]) { + using namespace std::chrono_literals; + const int nproc = std::thread::hardware_concurrency(); + std::vector<std::tuple<int, std::jthread, std::future<bool>>> workers(nproc); + //workers.resize(nproc); + for (int i=0; i<INT_MAX-(int)workers.size(); i+=workers.size()) { + //printf("process batch %d\n", i); + for (int n=i%workers.size(); n<(int)workers.size(); ++n) { + //printf("start worker %d (%d)\n", n, i+n); + std::get<0>(workers[n]) = i+n; + std::promise<bool> pr; + std::get<2>(workers[n]) = pr.get_future(); + std::get<1>(workers[n]) = std::jthread([](const Data &input, int a, auto &&out) { + Cpu cpu; + cpu.a = a; + Data derived = read_data(cpu.run(input)); + if (derived==input) cpu.print(); + out.set_value(derived==input); + //std::this_thread::sleep_for(1s); + }, input, i+n, std::move(pr)); + } + for (auto &w:workers) { + auto &[a, th, out] = w; + th.join(); + //printf("worker (%d) finished\n", a); + if (out.get()) return a; + } + } + return -1; +} + +int64_t part2_reverse(const Data &input) { + Cpu cpu; + std::vector<int> psbl; + for (int i=1; i<INT_MAX; ++i) { + cpu.reset(); + cpu.a = i; + std::string str = cpu.run(input); + //std::cout << "str:" << str << std::endl; + std::istringstream ss(str); + std::vector<int> vals; + for (std::string sn; std::getline(ss, sn, ',');) { + //std::cout << sn; + vals.push_back(std::stoi(sn)); + } + //std::printf("last val: %d\n", vals.back()); + if (input.back().second==vals.back()) psbl.push_back(i); + } + return psbl.size(); } int main(int argc, char **argv) { @@ -117,7 +190,7 @@ int main(int argc, char **argv) { std::cout << "AoC 2024 day 17 " << fname << std::endl; auto [cpu, input] = read_file(fname); std::cout << "part1: " << part1(cpu, input) << std::endl; - std::cout << "part2: " << part2(input) << std::endl; + std::cout << "part2: " << part2_reverse(input) << std::endl; return 0; } diff --git a/day17/test2.txt b/day17/test2.txt @@ -0,0 +1,5 @@ +Register A: 2024 +Register B: 0 +Register C: 0 + +Program: 0,3,5,4,3,0