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)); } 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; } 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)); }