I've had an unusually bad day. My phone screen broke, so I'm sending it in to get fixed, but in the process, a factory reset on it wiped all authenticators. Turns out, all of my 2-FA is associated with that phone - either the Auth app, or the phone number associated with the sim card. So I haven't been able to use one of my old phones as a backup phone; only because I can't log in. I have to wait for 72 hours to potentially log in. I have to live with no usable phone for 72 hours.
I realize it's probably a very first-world problem; it doesn't really affect me poorly, but it was a sudden and frustrating experience that's still going to affect me until my phone is returned.
This one's input seems simple.... almost too simple. Oh boy this mean it's going to be a bit of a pain.
At least the problem itself doesn't seem too bad - basically just implement a very-limited scope CPU.
bool jumped = false;
int op = program[I + 1];
switch (program[I])
{
case 0: A /= (int)Math.Pow(2, GetCombo(op)); break;
case 1: B ^= op; break;
case 2: B = GetCombo(op) % 8; break;
case 3: if (A != 0) { I = op; jumped = true; } break;
case 4: B ^= C; break;
case 5: output.Add(GetCombo(op) % 8); break;
case 6: B = A / (int)Math.Pow(2, GetCombo(op)); break;
case 7: C = A / (int)Math.Pow(2, GetCombo(op)); break;
}
That was... deceptively simple I think. It was odd the output itself was a string instead of some numerical value; I suppose this is the first problem year with something like that. I wonder if I'll need to modify the base program runner to deal with it, or just allow for -1
values and print statements?
Ah, here's the catch - finding the correct value.
I don't think it'll be too difficult; my output ran the whole program initially in 71 steps, though it may take much longer... hmm... maybe today's problem was just making this computer?
The naieve approach of just trying every possability isn't quite working. But looking at it run for a while, it seems to be printing out a bunch of numbers in octal. It seems to get longer the higher value of A there is, so it's probably a fairly large number judging by the length of the program.
I'll probably have to figure out what it actually does to better zero in on an answer... though I realize that the program may be very individual for me.
My findings:
- The weird power division things are all bitshifts (
<<
) - The entire program loops until A = 0
- First thing done is getting the first 3 bits of A
- Just before the check it bitshifts A down by 3
- Everything is in octal - meaning 3 bits is a number
Basically, my program is:
- Taking the least significant 3 bits of A
- Performing some operation
- Outputting the result
I have a feeling most people's inputs are the same. I need to reverse this operation somehow, then I can reverse-engineer the expected value of A based on the program - maybe even just outright run the program backwards?
bst A
bxl 1
cdv B
bxl 5
bxc
out B
adv 3
jnz 0
Okay, after an hour of banging my head against the problem like that, it wasn't working.
I decided to try and "brute-force" it, but a bit smarter; Test for each individual digit again, recursively, but on each level test to see if the last N digits of the program match the output. (And I will fully admit, I read some of reddit to see what other people were trying).
private List<long> ProgramDFS(long val, int depth)
{
var results = new List<long>();
if (depth > program.Length) return results;
long depthTest = val << 3;
for (uint i = 0; i < 8; i++)
{
long test = depthTest + i;
var computer = new Computer(test, b, c, program);
computer.Run();
if (computer.output.SequenceEqual(program.TakeLast(depth + 1)))
{
if (depth + 1 == program.Length) results.Add(test);
results.AddRange(ProgramDFS(test, depth + 1));
}
}
return results;
}