aoc2020/day8/part2/main.d

89 lines
2.1 KiB
D

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