summaryrefslogtreecommitdiff
path: root/2018/aoc2018-d19.py
blob: 51ad39eb5e7004222af52934bb9a3cfa058f1139 (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#advent of code 2018 
#day 19
#part 1 and part 2

#part 1 was very easy since it reused day 16 instructions
#for part 2 I was at first tricked by the maximum value stored in the register
#then I was tricked again by the value that was increasing by constant value
#which is really stupid on my part because I forgot that the answer to puzzle
#was value stored at register [0] - so none of the two above
#the value at reg[0] stores a sum of all divisors of 
#the max value mentioned before
#it took me a while to understand it - that was a tricky part 2 (as usual)

###opcode functions
#bit modified version of day 16 - removed 'after' list
def addr(before, op):
	bef = before.copy();
	C = bef[op[1]] + bef[op[2]];
	bef[op[3]] = C;
	return bef;
def addi(before, op):
	bef = before.copy();
	C = bef[op[1]] + op[2];
	bef[op[3]] = C;
	return bef;

def mulr(before, op):
	bef = before.copy();
	C = bef[op[1]] * bef[op[2]];
	bef[op[3]] = C;
	return bef;
def muli(before, op):
	bef = before.copy();
	C = bef[op[1]] * op[2];
	bef[op[3]] = C;
	return bef;

def banr(before, op):
	bef = before.copy();
	C = int(bef[op[1]] & bef[op[2]]);
	bef[op[3]] = C;
	return bef;
def bani(before, op):
	bef = before.copy();
	C = int(bef[op[1]] & op[2]);
	bef[op[3]] = C;
	return bef;

def borr(before, op):
	bef = before.copy();
	C = int(bef[op[1]] | bef[op[2]]);
	bef[op[3]] = C;
	return bef;
def bori(before, op):
	bef = before.copy();
	C = int(bef[op[1]] | op[2]);
	bef[op[3]] = C;
	return bef;

def setr(before, op):
	bef = before.copy();
	C = bef[op[1]];
	bef[op[3]] = C;
	return bef;
def seti(before, op):
	bef = before.copy();
	C = op[1];
	bef[op[3]] = C;
	return bef;

def gtir(before, op):
	bef = before.copy();
	C = 0 + int( op[1] > bef[op[2]] );
	bef[op[3]] = C;
	return bef;
def gtri(before, op):
	bef = before.copy();
	C = 0 + int( op[2] < bef[op[1]] );
	bef[op[3]] = C;
	return bef;
def gtrr(before, op):
	bef = before.copy();
	C = 0 + int( bef[op[1]] > bef[op[2]] );
	bef[op[3]] = C;
	return bef;

def eqir(before, op):
	bef = before.copy();
	C = 0 + int( op[1] == bef[op[2]] );
	bef[op[3]] = C;
	return bef;
def eqri(before, op):
	bef = before.copy();
	C = 0 + int( op[2] == bef[op[1]] );
	bef[op[3]] = C;
	return bef;
def eqrr(before, op):
	bef = before.copy();
	C = 0 + int( bef[op[1]] == bef[op[2]] );
	bef[op[3]] = C;
	return bef;

MatchFunctions = {};
MatchFunctions.update({"addr":addr});
MatchFunctions.update({"addi":addi});
MatchFunctions.update({"mulr":mulr});
MatchFunctions.update({"muli":muli});
MatchFunctions.update({"banr":banr});
MatchFunctions.update({"bani":bani});
MatchFunctions.update({"borr":borr});
MatchFunctions.update({"bori":bori});
MatchFunctions.update({"setr":setr});
MatchFunctions.update({"seti":seti});
MatchFunctions.update({"gtir":gtir});
MatchFunctions.update({"gtri":gtri});
MatchFunctions.update({"gtrr":gtrr});
MatchFunctions.update({"eqir":eqir});
MatchFunctions.update({"eqri":eqri});
MatchFunctions.update({"eqrr":eqrr});
	
#end of day16 copy-paste
###############################################

f = open("input.txt",'r');
Testing = False;
#Testing = True; 
if Testing:
	f.close();
	f = open("testinput.txt",'r');

ip = int(f.readline()[4:]);
instructions = [];

for l in f:
	l = l.split();
	i = [];
	i.append(l[0]);
	l_i = [int(x) for x in l[1:]];
	i += l_i;
	instructions.append(i);

instr_lim = len(instructions);
reg = [0,0,0,0,0,0];
reg[ip] = 0;
	
while True:	
	if( reg[ip] >= instr_lim): break;
	instr = instructions[reg[ip]];
	fun = MatchFunctions[instr[0]];
	reg = fun(reg,instr);
	
	reg[ip] += 1;

part1 = reg[0];
print("part 1 = ", part1);

reg = [1,0,0,0,0,0];
reg[ip] = 0;
counter = 1;

while True:	
	if( reg[ip] >= instr_lim): break;
	instr = instructions[reg[ip]];
	fun = MatchFunctions[instr[0]];
	reg = fun(reg,instr);
	
	if (counter%1000 == 0):
		print(reg);
		y1 = reg[1];
		break;

	reg[ip] += 1;
	counter += 1;

maxval = max(reg);
part2 = 0;
for x in range(1,maxval+1):
	if maxval%x == 0: part2 += x;

print("part 2 = ", part2);