diff --git a/day 17/day_17_max_n.cpp b/day 17/day_17_max_n.cpp new file mode 100644 index 0000000000000000000000000000000000000000..93390003dce59e20fe74bcf93bd93537d8a72c46 --- /dev/null +++ b/day 17/day_17_max_n.cpp @@ -0,0 +1,204 @@ +#include <bits/stdc++.h> + +#ifdef LOCAL +#include "./cpp-dump/cpp-dump.hpp" +#define pr(x) cpp_dump(x) +#endif + +using namespace std; + +#define Mod(x,y) (((x)%(y)+(y))%(y)) +#define rep(i, a, b) for(ll (i) = (a); (i) < (b); ++(i)) +#define all(x) begin(x), end(x) +#define pb push_back +#define gcd __gcd +#define sz(x) (ll)(x.size()) + +typedef long long ll; +typedef unsigned long long ull; +typedef pair<ll, ll> pii; +typedef vector<ll> vi; +typedef vector<pii> vii; + +const bool debug = false; + +vector<ll> reg = {0, 0, 0}; +vector<ll> output, A_bin; + +ll pointer = 0; + +ll get_operand(ll x) { + if (x >= 0 && x <= 3) return x; + if (x >= 4 && x <= 6) return reg[x-4]; + assert(false); + return 0; +} + +ll instruction(ll opcode, ll x) { + ll res = LLONG_MAX; + bool ok = true; + ll combo = get_operand(x); + if (opcode == 0) { + ll num = reg[0]; + ll den = 1; + rep(i, 0, combo) { + den *= 2; + if (den > num) break; + } + reg[0] = num/den; + } else if (opcode == 1) { + reg[1] = reg[1]^x; + } else if (opcode == 2) { + reg[1] = Mod(combo, 8); + } else if (opcode == 3) { + if (reg[0] != 0) { + ok = false; + pointer = x; + } + } else if (opcode == 4) { + reg[1] = reg[1]^reg[2]; + } else if (opcode == 5) { + res = Mod(combo, 8); + output.pb(res); + } else if (opcode == 6) { + ll num = reg[0]; + ll den = 1; + rep(i, 0, combo) { + den *= 2; + if (den > num) break; + } + reg[1] = num/den; + } else if (opcode == 7) { + ll num = reg[0]; + ll den = 1; + rep(i, 0, combo) { + den *= 2; + if (den > num) break; + } + reg[2] = num/den; + } + + if (ok) pointer+=2; + return res; +} + +bool same(vector<ll> instructions, ll A) { + reg[0] = reg[1] = reg[2] = 0; + reg[0] = A; + output.clear(); + pointer = 0; + int ind = 0; + while(pointer < instructions.size()) { + if (debug) { + pr(instructions[pointer]); + pr(instructions[pointer+1]); + } + ll res = instruction(instructions[pointer], instructions[pointer+1]); + if (debug) pr(reg); + + if (instructions.size() < output.size()) return false; + if (res < LLONG_MAX) { + if (instructions[ind] != res) return false; + ind++; + } + } + + if (instructions.size() != output.size()) return false; + rep(i, 0, sz(instructions)) if (instructions[i] != output[i]) return false; + + return true; +} + +vi generate(int a_3, int a_2, int a_1) { + vector<int> a3s, a2s, a1s; + if (a_3 == -1) a3s = {0, 1}; + else a3s = {a_3}; + if (a_2 == -1) a2s = {0, 1}; + else a2s = {a_2}; + if (a_1 == -1) a1s = {0, 1}; + else a1s = {a_1}; + + vi res; + for (int a3 : a3s) for (int a2 : a2s) for (int a1 : a1s) res.pb(4*a3 + 2*a2 + a1); + return res; +} + +vi to_bin(int x) { + vi res = {(x>>2)&1, (x>>1)&1, x&1}; + return res; +} + +bool valid(int ptr, int x) { + rep(i, 0, 3) if (A_bin[ptr-i] != -1 && A_bin[ptr-i] != to_bin(x)[i]) return false; + return true; +} + +ll get_ans() { + int i = 127; + ll ans = 0; + while(A_bin[i] != 1) { + i--; + } + while(i >= 0) { + ans = 2*ans + (A_bin[i] == 1 ? 1 : 0); + i--; + } + return ans; +} + +vector<ll> instructions; +bool pos(int instruction_ind) { + if (instruction_ind == sz(instructions)) { + return same(instructions, get_ans()); + } + bool res = false; + int ptr = 3*instruction_ind+2; + int a_3 = A_bin[ptr], a_2 = A_bin[ptr-1], a_1 = A_bin[ptr-2]; + int v0 = instructions[instruction_ind]; + vi minus_ones_pre; + rep(i, 0, 3) if (A_bin[ptr-i] == -1) minus_ones_pre.pb(i); + + for (int a : generate(a_3, a_2, a_1)) { + A_bin[ptr] = to_bin(a)[0]; + A_bin[ptr-1] = to_bin(a)[1]; + A_bin[ptr-2] = to_bin(a)[2]; + + int X = v0^(a^6); + + int new_ptr = ptr+(a^3); + + if (valid(new_ptr, X)) { + vi minus_ones; + rep(i, 0, 3) if (A_bin[new_ptr-i] == -1) minus_ones.pb(i); + rep(i, 0, 3) if (A_bin[new_ptr-i] = to_bin(X)[i]); + + if (pos(instruction_ind+1)) return true; + for (int i : minus_ones) A_bin[new_ptr-i] = -1; + } + } + for (int i : minus_ones_pre) A_bin[ptr-i] = -1; + return false; +} + +void solve() { + cin >> reg[0] >> reg[1] >> reg[2]; + ll x; + while(cin >> x) instructions.pb(x); + + rep(i, 0, 128) A_bin.pb(-1); + bool ok = pos(0); + ll ans = get_ans(); + pr(ans); +} + + +int main() { + ios::sync_with_stdio(0);cin.tie(0); + cout << setprecision(15) << fixed; + +#ifdef LOCAL + freopen("input.txt", "r", stdin); +#endif + + solve(); +}