summaryrefslogtreecommitdiff
path: root/2020/aoc2020-d08.py
blob: 89655141dba01ddcc596df00cb4aae10e114a8a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#advent of code 2020
#day 08
#a little bit bruteforce-ish, 
#for part 2 I mark instruction that are actually used by boot code
#then I loop over the marked instructions and replace them 1 by 1 until 
#the infinite cycle is broken
#also the input kept getting broken and needed to change the parsing
#which isn't a hard bug, but an annoying one
#ALSO during rewriting I figured out that I don't need to calculate 
#part 1 separately, it's already used during cycle detection
#although this might just be a coincidence; honestly I'm not confident
#in cycle detection puzzles

BootCode = []
PuzzleInput = open("08.in","r")
for x in PuzzleInput:
	if len(x) == 0: continue; #please ignore it, I'm bad at parsing
	instr, val = x.split(" ");
	BootCode.append(x.replace("\n",""));
PuzzleInput.close();

index = 0;
accumulator = 0;
visited = set();
#the "Im sure it works" method for part 1
while True:
	instr, val = BootCode[index].split(" ");
	#order += 1;
	if index in visited: break;
	visited.add(index);
	if instr == "nop": 
		index += 1;
	elif instr == "acc":
		accumulator += int(val);
		index += 1;
	elif instr == "jmp": 
		index += int(val);

print("part 1 =",accumulator);

index = 0;
accumulator = 0;
accVals = dict();
p1 = None;
#the "it works for me but might be luck" method for part 1
while index <= len(BootCode):
	instr, val = BootCode[index].split(" ");
	Current, Previous = accVals.get(index,(None,None));
	if Previous and Current and Previous%accumulator == Previous%accumulator:
		p1 = Current;
		break;
	accVals[index] = (accumulator, Current);
	if instr == "nop": 
		index += 1;
	elif instr == "acc":
		accumulator += int(val);
		index += 1;
	elif instr == "jmp": 
		index += int(val);

print("part 1 =",p1);

p2 = None;
for i in accVals:
	if BootCode[i].split(" ")[0] == "acc": continue;
	index = 0;
	accumulator = 0;
	accValsNested = dict();
	NoCycle = True;
	while index < len(BootCode):
		instr, val = BootCode[index].split(" ");
		Current, Previous = accValsNested.get(index,(None,None));
		if Previous and Current and Previous%accumulator == Previous%accumulator:
			NoCycle = False;
			break;
		accValsNested[index] = (accumulator, Current);
		if index == i: #swap instructions
			if instr == "nop": 
				instr = "jmp";
			elif instr == "jmp":
				instr = "nop";
		if instr == "nop": 
			index += 1;
		elif instr == "acc":
			accumulator += int(val);
			index += 1;
		elif instr == "jmp": 
			index += int(val);
	if NoCycle:
		p2 = accumulator;
		break;

print("part 2 =", p2);