2020-12-08 12:24:06 +01:00
|
|
|
import std;
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
"input".slurp!(string, int)("%s %s").fixProgramAndReturnAcc[0].writeln;
|
|
|
|
}
|
|
|
|
|
|
|
|
alias Instruction = Tuple!(string, int);
|
|
|
|
alias Program = Instruction[];
|
|
|
|
|
|
|
|
auto executeProgramAndReturnAcc(Program program)
|
|
|
|
{
|
|
|
|
int accumulator;
|
|
|
|
// dfmt off
|
|
|
|
alias operation = void delegate(ref ulong ip, int arg);
|
|
|
|
operation[string] operations = [
|
|
|
|
"nop" : (scope ref size_t ip, int arg) {ip += 1;},
|
|
|
|
"acc" : (scope ref size_t ip, int arg) { accumulator += arg; ip += 1; },
|
|
|
|
"jmp" : (scope ref size_t ip, int arg) {ip += arg;}
|
|
|
|
];
|
|
|
|
// dfmt on
|
|
|
|
void[0][size_t] seenIPs;
|
|
|
|
size_t ip = 0;
|
|
|
|
while (ip !in seenIPs && ip < program.length)
|
|
|
|
{
|
|
|
|
seenIPs[ip] = [];
|
|
|
|
operations[program[ip][0]](ip, program[ip][1]);
|
|
|
|
}
|
|
|
|
return tuple(accumulator, ip == program.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
unittest
|
|
|
|
{
|
|
|
|
auto program = `nop +0
|
|
|
|
acc +1
|
|
|
|
jmp +4
|
|
|
|
acc +3
|
|
|
|
jmp -3
|
|
|
|
acc -99
|
|
|
|
acc +1
|
|
|
|
jmp -4
|
|
|
|
acc +6`.splitter("\n").filter!(not!empty)
|
|
|
|
.map!((line) {
|
|
|
|
auto opAndArg = line.split(" ");
|
|
|
|
return tuple(opAndArg[0], opAndArg[1].to!int);
|
|
|
|
})
|
|
|
|
.array;
|
|
|
|
|
|
|
|
assert(program.executeProgramAndReturnAcc == tuple(5, false));
|
|
|
|
}
|
|
|
|
|
2020-12-08 12:25:23 +01:00
|
|
|
auto fixProgramAndReturnAcc(Program program)
|
|
|
|
{
|
|
|
|
return program.enumerate
|
|
|
|
.map!((indexedInstruction) {
|
|
|
|
if (indexedInstruction.value[0] == "acc")
|
|
|
|
return tuple(0, false);
|
|
|
|
else if (indexedInstruction.value[0] == "nop")
|
|
|
|
indexedInstruction.value[0] = "jmp";
|
|
|
|
else
|
|
|
|
indexedInstruction.value[0] = "nop";
|
|
|
|
|
|
|
|
return (program[0 .. indexedInstruction.index]
|
|
|
|
~ [indexedInstruction.value] ~ program[indexedInstruction.index + 1 .. $])
|
|
|
|
.executeProgramAndReturnAcc;
|
|
|
|
})
|
|
|
|
.find!(result => result[1])
|
|
|
|
.front;
|
|
|
|
}
|
|
|
|
|
2020-12-08 12:24:06 +01:00
|
|
|
unittest
|
|
|
|
{
|
|
|
|
auto program = `nop +0
|
|
|
|
acc +1
|
|
|
|
jmp +4
|
|
|
|
acc +3
|
|
|
|
jmp -3
|
|
|
|
acc -99
|
|
|
|
acc +1
|
|
|
|
jmp -4
|
|
|
|
acc +6`.splitter("\n").filter!(not!empty)
|
|
|
|
.map!((line) {
|
|
|
|
auto opAndArg = line.split(" ");
|
|
|
|
return tuple(opAndArg[0], opAndArg[1].to!int);
|
|
|
|
})
|
|
|
|
.array;
|
|
|
|
|
|
|
|
assert(program.fixProgramAndReturnAcc == tuple(8, true));
|
|
|
|
}
|