Are you participating in the Advent of code this year?
If you don't know what the advent of code is, it's a website where you'll find a daily challenge (every day it gets harder). It's a really fun event, you should participate!
I try to solve the exercises using either JavaScript or TypeScript and will share my solutions daily (with one day delay so no one can cheat!). I only share the solution for the second part.
When I saw the exercise for day #8, I really though "oh boy, this one is going to be hardcore". I thought we'd need to implement a runtime for their weird assembly-like language. Lucky for us, this was way easier than what I assumed!
I basically just wrote a function that determines if the program exits successfully or not, and then run it agains every possible version of the assembly-like code. Here is what it looks like:
const SUCCESS = "SUCCESS";
const ERROR = "ERROR";
// Runs the program, and return SUCCESS or ERROR
// Depending on whether or not it finished (line number > code.length)
function runProgram(code) {
// If a line is processed 2 times, it's an error
const alreadyProcessed = [];
let global = 0;
let currentLine = 0;
while (true) {
if (alreadyProcessed[currentLine] === true) return { global, status: ERROR, alreadyProcessed };
if (code[currentLine] === undefined)
return { global, status: SUCCESS, alreadyProcessed };
alreadyProcessed[currentLine] = true;
const [inst, argument] = code[currentLine];
switch (inst) {
case "acc":
global += parseInt(argument, 10);
currentLine += 1;
break;
case "jmp":
currentLine += parseInt(argument, 10);
break;
case "nop":
currentLine += 1;
break;
default:
throw new Error(inst);
}
}
}
// Let's just bruteforce, and run the program changing any
// line that is a nop or a jmp to find which one is corrupted
input.forEach((_value, index) => {
const code = [...input];
const [inst, argument] = code[index];
if (inst === "jmp") code[index] = ["nop", argument];
else if (inst === "nop") code[index] = ["jmp", argument];
const altResult = runProgram(code);
if (altResult.status === "SUCCESS") console.log(altResult);
});
Feel free to share your solution in the comments!
Photo by Markus Spiske on Unsplash
Top comments (1)
Dec 8, 2020
Part 1
import pandas as pd
df = pd.read_csv('12082020adventofcode.txt', sep=' ',
header=None, names=['Instruction', 'Argument'])
ind_list = list(range(0, len(df)))
ind_flip = []
acc_value = 0
ind = 0
copy_ind = 0
def acc(arg):
global acc_value
acc_value += arg
global ind
ind += 1
def jmp(arg):
global ind
ind += arg
def nop(arg):
global ind
ind += 1
while ind in ind_list:
copy_ind = ind
instr = df.loc[ind,'Instruction']
argu = df.loc[ind,'Argument']
ind_list.remove(ind)
global ind_flip
ind_flip.append(ind)
if instr == 'acc':
acc(argu)
elif instr == 'jmp':
jmp(argu)
elif instr == 'nop':
nop(argu)
print('#####################################')
print('Part 1:')
print('final acc_value:', acc_value)
print('last run ind:', copy_ind)
print(df.loc[copy_ind,:])
print('repeated ind:', ind)
print(df.loc[ind,:])
print('ind_flip for part 2:', ind_flip)
print('#####################################')
part 2
ind_list = list(range(0, len(df)))
acc_value = 0
ind = 0
copy_ind = 0
def flip(row):
instru = df.loc[row,'Instruction']
if instru == 'jmp':
df.loc[row,'Instruction'] = 'nop'
elif instru == 'nop':
df.loc[row,'Instruction'] = 'jmp'
def while_loop(x):
global ind
ind = x
while ind in ind_list:
instr = df.loc[ind,'Instruction']
argu = df.loc[ind,'Argument']
global copy_ind
copy_ind = ind
ind_list.remove(ind)
if instr == 'acc':
acc(argu)
elif instr == 'jmp':
jmp(argu)
elif instr == 'nop':
nop(argu)
for i in ind_flip:
flip(int(i))
while_loop(ind)
flip(int(i))
if copy_ind == len(df)-1:
break
ind_list = list(range(0, len(df)))
acc_value = 0
ind = 0
copy_ind = 0
print('#####################################')
print('Part 2:')
print('last run ind:', copy_ind)
print('final acc_value:', acc_value)
print(df.loc[copy_ind,:])
print('#####################################')