summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorb-idea <test@test.com>2023-09-28 13:25:01 +0200
committerb-idea <test@test.com>2023-09-28 13:25:01 +0200
commitc1fdc53e46d456d6bfa4f5a416a1e58e8a6468ef (patch)
tree4ce8a0fec0fff5bb9fafb89546d195eca81c006f
parent3d1bbf7d8f051a8b8c8473cac699a91f8e87dfda (diff)
added days: 10,11,12,14,16,18
-rwxr-xr-x2018/aoc2018-d10.py88
-rwxr-xr-x2018/aoc2018-d11-p1.py75
-rwxr-xr-x2018/aoc2018-d11-p2.py108
-rw-r--r--2018/aoc2018-d12.py68
-rw-r--r--2018/aoc2018-d14.py66
-rw-r--r--2018/aoc2018-d16.py359
-rw-r--r--2018/aoc2018-d18.py131
7 files changed, 895 insertions, 0 deletions
diff --git a/2018/aoc2018-d10.py b/2018/aoc2018-d10.py
new file mode 100755
index 0000000..7bd2ae5
--- /dev/null
+++ b/2018/aoc2018-d10.py
@@ -0,0 +1,88 @@
+#advent of code 2018
+#day 10
+
+#part 1 & part 2
+
+class light:
+ def __init__(self, x,y,vx,vy):
+ self.Pos = [x,y];
+ self.Vel = [vx,vy];
+ def CalcNextPos(self, t):
+ return [self.Pos[0]+t*self.Vel[0],self.Pos[1]+t*self.Vel[1]];
+ def __str__(self):
+ return f'<{self.Pos[0]},{self.Pos[1]}>';
+
+def CalcArea(x1,x2,y1,y2):
+ return abs(x1-x2)*abs(y1-y2);
+
+f = open("input.txt",'r');
+Testing = False;
+#Testing = True;
+if Testing:
+ f.close();
+ f = open("testinput.txt",'r');
+
+lights = [];
+
+for tl in f:
+ tl = tl.replace("position=<", "");
+ tl = tl.replace("velocity=<", "");
+ tl = tl.replace(">", "");
+ tl = tl.replace(",", "");
+ tl=tl.split();
+ lights.append( light(int(tl[0]),int(tl[1]),int(tl[2]),int(tl[3])) );
+f.close();
+
+Xmin = min(lights, key = lambda x: x.Pos[0]).Pos[0];
+Xmax = max(lights, key = lambda x: x.Pos[0]).Pos[0];
+Ymin = min(lights, key = lambda y: y.Pos[1]).Pos[1];
+Ymax = max(lights, key = lambda y: y.Pos[1]).Pos[1];
+#print(Xmin,Xmax,Ymin,Ymax);
+
+PrevArea = CalcArea(Xmin,Xmax,Ymin,Ymax);
+ElapsedTime = 0;
+
+while True:
+ #print(ElapsedTime);
+ ElapsedTime += 1;
+ Xmin = min(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[0]).CalcNextPos(ElapsedTime)[0];
+ Xmax = max(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[0]).CalcNextPos(ElapsedTime)[0];
+ Ymin = min(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[1]).CalcNextPos(ElapsedTime)[1];
+ Ymax = max(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[1]).CalcNextPos(ElapsedTime)[1];
+
+ CurrArea = CalcArea(Xmin,Xmax,Ymin,Ymax);
+
+ if (CurrArea > PrevArea):
+ MessageTime = ElapsedTime-1;
+ break;
+
+ PrevArea = CurrArea;
+
+pointlist = [];
+
+for l in lights:
+ xy = l.CalcNextPos(MessageTime);
+ pointlist.append((xy[0],xy[1]));
+
+Xmin = min(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[0]).CalcNextPos(ElapsedTime)[0];
+Xmax = max(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[0]).CalcNextPos(ElapsedTime)[0];
+Ymin = min(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[1]).CalcNextPos(ElapsedTime)[1];
+Ymax = max(lights, key = lambda L: L.CalcNextPos(ElapsedTime)[1]).CalcNextPos(ElapsedTime)[1];
+
+
+print("###########");
+print("part1:");
+
+for Y in range(Ymin,Ymax+1):
+ for X in range(Xmin,Xmax+1):
+ sign = " ";
+ if ((X,Y) in pointlist):
+ sign = "#";
+ print(sign, end="");
+ #print(end="");
+ print();
+
+part2 = MessageTime;
+
+print("###########");
+print("part2 ,", part2);
diff --git a/2018/aoc2018-d11-p1.py b/2018/aoc2018-d11-p1.py
new file mode 100755
index 0000000..2379c3c
--- /dev/null
+++ b/2018/aoc2018-d11-p1.py
@@ -0,0 +1,75 @@
+#advent of code 2018
+#day 11
+#part 1
+
+#setup
+GridSize = 300;
+SquareSize = 3;
+fcserialnumber = int(open("input.txt",'r').readline());
+
+testing = False;
+#testing = True;
+if testing:
+ fcserialnumber = 42; #18=>33,45 ; 42 => 21,61;
+
+class fuelcell:
+ def __init__(self, x, y, serialnumber):
+ self.positionX = x;
+ self.positionY = y;
+ self.rackID = self.positionX + 10;
+ self.powerlevel = self.rackID * self.positionY;
+ self.powerlevel += serialnumber;
+ self.powerlevel *= self.rackID;
+ self.powerlevel = self.powerlevel//100;
+ self.powerlevel = self.powerlevel%10;
+ self.powerlevel -= 5;
+ def coords(self):
+ print(f'Fuel Cell coordinates (x,y): {self.positionX},{self.positionY} ');
+ def __str__(self):
+ return f'{self.powerlevel}';
+
+'''
+testinput = [[3,5,8],[122,79,57],[217,196,39],[101,153,71]];
+
+for t in testinput:
+ dummycell = fuelcell(t[0],t[1],t[2]);
+ print(t, " -> ",dummycell.powerlevel);
+ dummycell.coords();
+
+print("#############################");
+print();
+'''
+
+fcgrid = [];
+gridline = [];
+
+for Y in range(GridSize):
+ gridline.clear();
+ for X in range(GridSize):
+ gridline.append(fuelcell(X+1,Y+1,fcserialnumber));
+ fcgrid.append(gridline.copy());
+
+maxpower = -999; #negative power just to start the algorythm
+maxX = 0;
+maxY = 0;
+powernow = 0;
+
+for Y in range(GridSize-SquareSize+1):
+ for X in range(GridSize-SquareSize+1):
+ powernow = 0;
+ for sy in range(SquareSize):
+ for sx in range(SquareSize):
+ powernow += fcgrid[Y+sy][X+sx].powerlevel;
+ if (powernow > maxpower):
+ maxpower = powernow;
+ maxX = X;
+ maxY = Y;
+
+#print(f'maximum found: {maxX},{maxY} => {maxpower}');
+print("part 1: ");
+fcgrid[maxY][maxX].coords();
+
+#10,300 wrong
+#9,0 wrong
+#0,9 wrong
+#33,45
diff --git a/2018/aoc2018-d11-p2.py b/2018/aoc2018-d11-p2.py
new file mode 100755
index 0000000..dbfafe7
--- /dev/null
+++ b/2018/aoc2018-d11-p2.py
@@ -0,0 +1,108 @@
+#advent of code 2018
+#day 11
+#part 2
+#too lazy to clean up the code, might do it later (i.e. never)
+
+#setup
+GridSize = 300;
+SquareSize = 3;
+fcserialnumber = int(open("input.txt",'r').readline());
+
+testing = False;
+#testing = True;
+if testing:
+ fcserialnumber = 42; #18=>90,269,16 ; 42 => 21,61;
+
+class fuelcell:
+ def __init__(self, x, y, serialnumber):
+ self.positionX = x;
+ self.positionY = y;
+ self.rackID = self.positionX + 10;
+ self.powerlevel = self.rackID * self.positionY;
+ self.powerlevel += serialnumber;
+ self.powerlevel *= self.rackID;
+ self.powerlevel = self.powerlevel//100;
+ self.powerlevel = self.powerlevel%10;
+ self.powerlevel -= 5;
+ def coords(self):
+ print(f'Fuel Cell coordinates (x,y): {self.positionX},{self.positionY} ');
+ def __str__(self):
+ return f'{self.powerlevel}';
+
+'''
+testinput = [[3,5,8],[122,79,57],[217,196,39],[101,153,71]];
+
+for t in testinput:
+ dummycell = fuelcell(t[0],t[1],t[2]);
+ print(t, " -> ",dummycell.powerlevel);
+ dummycell.coords();
+
+print("#############################");
+print();
+'''
+
+fcgrid = [];
+gridline = [];
+
+print("#############################");
+print("INITIATE BATTERY ARRAY");
+for Y in range(GridSize):
+ gridline.clear();
+ for X in range(GridSize):
+ gridline.append(fuelcell(X+1,Y+1,fcserialnumber));
+ fcgrid.append(gridline.copy());
+
+print("#############################");
+print("CALCULATE SQUARE SUBSUMS");
+sumtable = [];
+
+gridline.clear();
+gridline.append(fcgrid[0][0].powerlevel);
+
+for X in range(1,GridSize):
+ SubSumFc = fcgrid[0][X].powerlevel + gridline[X-1];
+ gridline.append(SubSumFc);
+sumtable.append(gridline.copy());
+
+currentsubsum = 0;
+
+for Y in range(1,GridSize):
+ gridline.clear();
+ SubSumFc = sumtable[Y-1][0] + fcgrid[Y][0].powerlevel;
+ gridline.append(SubSumFc);
+ currentsubsum = fcgrid[Y][0].powerlevel;
+ for X in range(1,GridSize):
+ currentsubsum += fcgrid[Y][X].powerlevel;
+ gridline.append(sumtable[Y-1][X] + currentsubsum);
+ sumtable.append(gridline.copy());
+
+print("#############################");
+print("SEARCH FOR HIGHEST SUBSUM SQUARE");
+
+maxpower = -999;
+maxX = 0;
+maxY = 0;
+powernow = 0;
+maxsquare = 0;
+
+for Y in range(1,GridSize-3):
+ ssy = GridSize - Y;
+ for X in range(1,GridSize-3):
+ ssx = GridSize - X;
+ SquareSize = (ssx>=ssy)*ssy + ssx*(ssx<ssy);
+ for s in range(SquareSize):
+ powernow = 0;
+ powernow = sumtable[Y+s][X+s] - sumtable[Y-1][X+s] - sumtable[Y+s][X-1] + sumtable[Y-1][X-1];
+ if (powernow > maxpower):
+ maxX = X;
+ maxY = Y;
+ maxpower = powernow;
+ maxsquare = s;
+ #print("new max power: ", maxpower, " // ", powernow);
+
+print("#############################");
+print("Results:");
+print(maxX, "\t", maxY, "\t", maxsquare, "\t", maxpower);
+fcgrid[maxY][maxX].coords();
+print("winrar part 2:\t", fcgrid[maxY][maxX].positionX,",",fcgrid[maxY][maxX].positionY,",",maxsquare+1,end="");
+
diff --git a/2018/aoc2018-d12.py b/2018/aoc2018-d12.py
new file mode 100644
index 0000000..9922c39
--- /dev/null
+++ b/2018/aoc2018-d12.py
@@ -0,0 +1,68 @@
+#advent of code 2018
+#day 12
+#part 1 & part 2
+
+generationnumber1 = 20; #part1
+generationnumber2 = 10000; #steady state
+generationnumber3 = 50000000000; #part2
+
+f = open("input.txt", 'r');
+
+testing = False;
+#testing = True;
+if testing:
+ f.close();
+ f = open("testinput.txt", 'r');
+
+PlantInitialState = f.readline();
+PlantInitialState = PlantInitialState.replace("initial state: ","");
+PlantInitialState = PlantInitialState.replace("\n","");
+f.readline();
+
+Notes = {};
+
+for l in f:
+ n1 = l[0:5];
+ n2 = l[9];
+ Notes[n1] = n2;
+ print(l, end="");
+
+#append to the beginning and the end an a=4 amount of pots
+#store the amount of appended pots
+
+PlantInitialState = "...." + PlantInitialState + "....";
+a = 4;
+PlantCurrentState = PlantInitialState;
+
+part1 = 0;
+
+for g in range(generationnumber2):
+ substate = PlantCurrentState[0:2];
+ substate += Notes.get(PlantCurrentState[0:5]);
+ for p in range(3,len(PlantCurrentState)-2):
+ substate += Notes.get(PlantCurrentState[p-2:p+3]);
+ substate += PlantCurrentState[-2:];
+ if(substate[2] == '#'):
+ substate = ".." + substate;
+ a += 2;
+ if(substate[-3] == '#'):
+ substate = substate + "..";
+ PlantCurrentState = substate;
+ if (g == generationnumber1 -1):
+ for pot in range(len(PlantCurrentState)):
+ if PlantCurrentState[pot] == '#':
+ part1 += pot - a;
+
+
+SteadyState10k = 0;
+for pot in range(len(PlantCurrentState)):
+ if PlantCurrentState[pot] == '#':
+ SteadyState10k += pot - a;
+
+gendiv = generationnumber3//generationnumber2;
+part2 = SteadyState10k*(gendiv);
+
+print("part1: ", part1);
+print("part2: ", part2);
+
+#2830 too low
diff --git a/2018/aoc2018-d14.py b/2018/aoc2018-d14.py
new file mode 100644
index 0000000..9e042d0
--- /dev/null
+++ b/2018/aoc2018-d14.py
@@ -0,0 +1,66 @@
+#advent of code 2018
+#day 14
+#part 1 & part 2
+
+#there should be a faster way to compute the results
+#no idea how to do it at the moment
+
+import time
+
+f = open("input.txt",'r');
+myinput = int(f.readline());
+
+Testing = False;
+#Testing = True;
+if Testing:
+ f.close();
+ #f = open("testinput.txt",'r');
+ myinput = 9;
+ myinput = 5;
+ myinput = 18;
+ myinput = 2018;
+
+recipes = [3,7];
+elf1 = 0;
+elf2 = 1;
+
+StillSearching = True;
+part2 = "";
+
+ElapsedTime = 0;
+starttime = time.time();
+
+while (StillSearching):
+ newrecipes = recipes[elf1] + recipes[elf2];
+ newrecipes = str(newrecipes);
+ for r in newrecipes:
+ recipes.append(int(r));
+
+ move1 = 1 + recipes[elf1];
+ move2 = 1 + recipes[elf2];
+ elf1 = (move1 + elf1)%len(recipes);
+ elf2 = (move2 + elf2)%len(recipes);
+
+ recipesstring = "";
+ for n in range(-len(str(myinput))-1,0):
+ recipesstring += str( recipes[n%len(recipes)] );
+
+ if (recipesstring[:-1] == str(myinput)):
+ part2 = len(recipes) - len(str(myinput)) -1;
+ print("p2 ", part2);
+ elif (recipesstring[1:] == str(myinput)):
+ part2 = len(recipes) - len(str(myinput));
+ print("p2 ", part2);
+
+ if (len(recipes)>=myinput+10):
+ if (part2 != ""):
+ StillSearching = False;
+
+part1 = "";
+for i in range(myinput,myinput+10):
+ part1 += str(recipes[i]);
+
+endtime = time.time() - starttime;
+print("FIN -- ", endtime, "sec");
+print("part 1: ", part1);
+print("part 2: ", part2);
diff --git a/2018/aoc2018-d16.py b/2018/aoc2018-d16.py
new file mode 100644
index 0000000..3bb0dc1
--- /dev/null
+++ b/2018/aoc2018-d16.py
@@ -0,0 +1,359 @@
+#advent of code 2018
+#day 16
+#part 1 and part 2
+
+#when doing this puzzle I learned that I can make a list of functions and it just works
+#code could use a bit of clean up,
+#lots of multiple lines because of 16 functions
+#(I could save ~32 lines just by modifying the functions)
+#lots of work-arounds because I don't know to implement it efficently
+#but still, I got the results
+
+f = open("input.txt",'r');
+Testing = False;
+#Testing = True;
+if Testing:
+ f.close();
+ f = open("testinput.txt",'r');
+
+input_part1 = [];
+input_part2 = [];
+sublist = [];
+
+for l in f:
+ l = l.replace("\n","");
+ if (len(l) == 0):
+ input_part1.append( sublist.copy() );
+ sublist = [];
+ continue;
+ elif (l == "###"):
+ break;
+ elif (len(l) < 20):
+ sublist.append( [int(x) for x in l.split(" ")] );
+ elif (l[6] == ":"):
+ sublist.append( eval(l[7:]) );
+ elif (l[5] == ":"):
+ sublist.append( eval(l[7:]) );
+'''
+for i in input_part1:
+ print(i[0], "\t", i[1], "\t", i[2], "\t")
+'''
+
+for l in f:
+ l = l.replace("\n","");
+ input_part2.append( [int(x) for x in l.split(" ")] );
+
+'''
+print();
+print();
+print();
+for i in input_part2:
+ print(i);
+'''
+
+###opcode functions
+def addr(before, op, aft):
+ bef = before.copy();
+ C = bef[op[1]] + bef[op[2]];
+ bef[op[3]] = C;
+ return bef;
+def addi(before, op, aft):
+ bef = before.copy();
+ C = bef[op[1]] + op[2];
+ bef[op[3]] = C;
+ return bef;
+
+def mulr(before, op, aft):
+ bef = before.copy();
+ C = bef[op[1]] * bef[op[2]];
+ bef[op[3]] = C;
+ return bef;
+def muli(before, op, aft):
+ bef = before.copy();
+ C = bef[op[1]] * op[2];
+ bef[op[3]] = C;
+ return bef;
+
+def banr(before, op, aft):
+ bef = before.copy();
+ C = int(bef[op[1]] & bef[op[2]]);
+ bef[op[3]] = C;
+ return bef;
+def bani(before, op, aft):
+ bef = before.copy();
+ C = int(bef[op[1]] & op[2]);
+ bef[op[3]] = C;
+ return bef;
+
+def borr(before, op, aft):
+ bef = before.copy();
+ C = int(bef[op[1]] | bef[op[2]]);
+ bef[op[3]] = C;
+ return bef;
+def bori(before, op, aft):
+ bef = before.copy();
+ C = int(bef[op[1]] | op[2]);
+ bef[op[3]] = C;
+ return bef;
+
+def setr(before, op, aft):
+ bef = before.copy();
+ C = bef[op[1]];
+ bef[op[3]] = C;
+ return bef;
+def seti(before, op, aft):
+ bef = before.copy();
+ C = op[1];
+ bef[op[3]] = C;
+ return bef;
+
+def gtir(before, op, aft):
+ bef = before.copy();
+ C = 0 + int( op[1] > bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+def gtri(before, op, aft):
+ bef = before.copy();
+ C = 0 + int( op[2] < bef[op[1]] );
+ bef[op[3]] = C;
+ return bef;
+def gtrr(before, op, aft):
+ bef = before.copy();
+ C = 0 + int( bef[op[1]] > bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+
+def eqir(before, op, aft):
+ bef = before.copy();
+ C = 0 + int( op[1] == bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+def eqri(before, op, aft):
+ bef = before.copy();
+ C = 0 + int( op[2] == bef[op[1]] );
+ bef[op[3]] = C;
+ return bef;
+def eqrr(before, op, aft):
+ bef = before.copy();
+ C = 0 + int( bef[op[1]] == bef[op[2]] );
+ bef[op[3]] = C;
+ return bef;
+
+
+def threeormore(bef, op, aft):
+ fun = 1;
+ counter = 0;
+ out = aft.copy();
+ counter += int( out == addr(bef,op,aft) );
+ counter += int( out == addi(bef,op,aft) );
+ counter += int( out == mulr(bef,op,aft) );
+ counter += int( out == muli(bef,op,aft) );
+ counter += int( out == banr(bef,op,aft) );
+ counter += int( out == bani(bef,op,aft) );
+ counter += int( out == borr(bef,op,aft) );
+ counter += int( out == bori(bef,op,aft) );
+ counter += int( out == setr(bef,op,aft) );
+ counter += int( out == seti(bef,op,aft) );
+ counter += int( out == gtir(bef,op,aft) );
+ counter += int( out == gtri(bef,op,aft) );
+ counter += int( out == gtrr(bef,op,aft) );
+ counter += int( out == eqir(bef,op,aft) );
+ counter += int( out == eqri(bef,op,aft) );
+ counter += int( out == eqrr(bef,op,aft) );
+
+ return counter;
+ '''
+ if (counter >= 3):
+ return 1;
+ else:
+ return 0;
+'''
+
+part1 = 0;
+for sample in input_part1:
+ before = sample[0];
+ instruction = sample[1];
+ after = sample[2];
+ part1 += 1*(threeormore(before, instruction, after ) >=3);
+
+print("part 1 = ", part1);
+
+#776 yoo high
+#588 correct
+#my mistake - misunderstood bitwise AND and bitwise OR
+#they dont return a boolean, just a normal integer
+#my function was int(bool(value)), which was reducing the correct value to 1
+
+
+
+#identifying single matches
+'''
+singles = [];
+doubles = [];
+triples = [];
+
+for sample in input_part1:
+ before = sample[0];
+ instruction = sample[1];
+ after = sample[2];
+ if (threeormore(before, instruction, after ) == 1):
+ singles.append(instruction[0]);
+ if (threeormore(before, instruction, after ) == 2):
+ doubles.append(instruction[0]);
+ if (threeormore(before, instruction, after ) >= 3):
+ triples.append(instruction[0]);
+ #part1 += 1*(threeormore(before, instruction, after ) >=3);
+
+singles = list(dict.fromkeys(singles));
+doubles = list(dict.fromkeys(doubles));
+triples = list(dict.fromkeys(triples));
+
+print("singles\t",len(singles), "\t", singles);
+print("doubles\t",len(doubles), "\t", doubles);
+print("triples\t",len(triples), "\t", triples);
+'''
+
+
+
+def matchingfunctions(bef, op, aft):
+ functionlist = "";
+ out = aft.copy();
+ functionlist += "addr"*( out == addr(bef,op,aft) );
+ functionlist += "addi"*( out == addi(bef,op,aft) );
+ functionlist += "mulr"*( out == mulr(bef,op,aft) );
+ functionlist += "muli"*( out == muli(bef,op,aft) );
+ functionlist += "banr"*( out == banr(bef,op,aft) );
+ functionlist += "bani"*( out == bani(bef,op,aft) );
+ functionlist += "borr"*( out == borr(bef,op,aft) );
+ functionlist += "bori"*( out == bori(bef,op,aft) );
+ functionlist += "setr"*( out == setr(bef,op,aft) );
+ functionlist += "seti"*( out == seti(bef,op,aft) );
+ functionlist += "gtir"*( out == gtir(bef,op,aft) );
+ functionlist += "gtri"*( out == gtri(bef,op,aft) );
+ functionlist += "gtrr"*( out == gtrr(bef,op,aft) );
+ functionlist += "eqir"*( out == eqir(bef,op,aft) );
+ functionlist += "eqri"*( out == eqri(bef,op,aft) );
+ functionlist += "eqrr"*( out == eqrr(bef,op,aft) );
+
+ return (op[0],functionlist);
+
+singles = [];
+doubles = [];
+triples = [];
+
+for sample in input_part1:
+ before = sample[0];
+ instruction = sample[1];
+ after = sample[2];
+ if (threeormore(before, instruction, after ) == 1):
+ singles.append(matchingfunctions(before, instruction, after ));
+ if (threeormore(before, instruction, after ) == 2):
+ doubles.append(matchingfunctions(before, instruction, after ));
+ if (threeormore(before, instruction, after ) >= 3):
+ triples.append(matchingfunctions(before, instruction, after ));
+ #part1 += 1*(threeormore(before, instruction, after ) >=3);
+
+'''
+print("singles\t",len(singles), "\t", singles);
+print("doubles\t",len(doubles), "\t", doubles);
+print("triples\t",len(triples), "\t", triples);
+'''
+
+singles = list(dict.fromkeys(singles));
+doubles = list(dict.fromkeys(doubles));
+triples = list(dict.fromkeys(triples));
+
+'''
+for s in singles:
+ print(s);
+print();
+print();
+for s in doubles:
+ print(s);
+print();
+print();
+for s in triples:
+ print(s);
+print();
+print();
+'''
+
+PossibleFunctions = {};
+total = singles + doubles + triples;
+
+for t in total:
+ PossibleFunctions.update({t[0] : t[1]});
+
+'''
+for pf in PossibleFunctions:
+ print(pf,"\t", PossibleFunctions[pf]);
+ '''
+
+IdentifiedFunctions = {};
+
+
+while (len(IdentifiedFunctions) < 16):
+ for found in IdentifiedFunctions:
+ for possible in PossibleFunctions:
+ if (len(PossibleFunctions[possible]) > 4 ):
+ s = PossibleFunctions[possible];
+ s = s.replace(IdentifiedFunctions[found], "");
+ PossibleFunctions.update({possible : s});
+
+ for pf in PossibleFunctions:
+ if (len(PossibleFunctions[pf]) == 4 ):
+ IdentifiedFunctions.update({pf : PossibleFunctions[pf]});
+
+ '''
+ for pf in PossibleFunctions:
+ print(pf,"\t", PossibleFunctions[pf]);
+ input();
+ '''
+
+'''
+print();
+print();
+print();
+print("Identified Functions");
+for pf in IdentifiedFunctions:
+ print(pf,"\t", IdentifiedFunctions[pf]);
+'''
+
+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});
+
+for i in IdentifiedFunctions:
+ MatchFunctions.update({i:MatchFunctions[IdentifiedFunctions[i]]});
+
+'''
+print();
+print();
+print();
+print("Matched Functions");
+for pf in MatchFunctions:
+ print(pf,"\t", MatchFunctions[pf]);
+'''
+
+reg = [0,0,0,0];
+for i in input_part2:
+ f_i = MatchFunctions[i[0]];
+ reg = f_i(reg, i, [] );
+
+part2 = reg[0];
+#print(reg);
+print("part 2 = ", part2);
diff --git a/2018/aoc2018-d18.py b/2018/aoc2018-d18.py
new file mode 100644
index 0000000..8d85635
--- /dev/null
+++ b/2018/aoc2018-d18.py
@@ -0,0 +1,131 @@
+#advent of code 2018
+#day 18
+#part 1 and part 2
+
+#at first I thought I can find the loop by simply registering when a value "part2" is repeated once
+#(kind of like in an earlier puzzle for that year)
+#then I had a correct idea how to find the pattern,
+#but didn't really know how to implement it efficently
+#pattern recognition is an implementation of solution provided by Michael Fogleman
+#adjusted to my current code
+#another issue I had was that I resumed the calculations for part 2 from the state after 10 minutes (part1)
+#I needed to save the initial state and then start over
+#could probably reduce the code to single loop instead of two separate loops for each part
+
+f = open("input.txt",'r');
+Testing = False;
+#Testing = True;
+if Testing:
+ f.close();
+ f = open("testinput.txt",'r');
+
+size = 50;
+if Testing: size = 10;
+
+#part 1
+
+CurrentState = {};
+
+for r,l in enumerate(f):
+ #print(len(l));
+ for c,a in enumerate(l):
+ CurrentState.update({(r,c):a});
+InitialState = CurrentState.copy();
+f.close();
+
+for x in range(size):
+ for y in range(size):
+ print(CurrentState[(x,y)],end="");
+ print();
+
+#check if each adjacent position is still within grid range
+def GetAdjacent(Cords):
+ Adjacent = [];
+ if (Cords[0] -1 >= 0 and Cords[1]-1 >=0):
+ Adjacent.append( (Cords[0] -1,Cords[1]-1) );
+ if (Cords[0] -1 >= 0):
+ Adjacent.append( (Cords[0] -1,Cords[1]) );
+ if (Cords[0] -1 >= 0 and Cords[1]+1 < size):
+ Adjacent.append( (Cords[0] -1,Cords[1]+1) );
+ if (Cords[1]+1 < size):
+ Adjacent.append( (Cords[0],Cords[1]+1) );
+ if (Cords[1]-1 >= 0):
+ Adjacent.append( (Cords[0],Cords[1]-1) );
+ if (Cords[0] +1 < size and Cords[1]-1 >=0):
+ Adjacent.append( (Cords[0] +1,Cords[1]-1) );
+ if (Cords[0] +1 < size):
+ Adjacent.append( (Cords[0] +1,Cords[1]) );
+ if (Cords[0] +1 < size and Cords[1]+1 < size):
+ Adjacent.append( (Cords[0] +1,Cords[1]+1) );
+ return Adjacent;
+
+def GetAcres(area, adj):
+ acres = [];
+ for c in adj:
+ acres.append(area[c]);
+ return acres;
+
+def ChangeState(area, Cords):
+ s = area[Cords];
+ adj = GetAdjacent(Cords);
+ Acres = GetAcres(area, adj);
+ if (s == "." and Acres.count("|")>=3):
+ s = "|";
+ elif (s == "|" and Acres.count("#")>=3):
+ s = "#";
+ elif (s == "#" and Acres.count("#")>=1 and Acres.count("|")>=1):
+ s = "#";
+ elif (s == "#"):
+ s = ".";
+ return s;
+
+SimTime = 10; #minutes
+
+InitialState = CurrentState.copy();
+for t in range(SimTime):
+ NextState = {};
+ for x in range(size):
+ for y in range(size):
+ NextState.update({(x,y):ChangeState(CurrentState,(x,y))});
+ CurrentState = NextState.copy();
+ '''
+ print("MINUTE ",t);
+ for x in range(size):
+ for y in range(size):
+ print(CurrentState[(x,y)],end="");
+ print();
+ print();
+ '''
+summary = list(CurrentState.values());
+
+woods = summary.count("|");
+lumbs = summary.count("#");
+part1 = woods*lumbs;
+print("part 1 = ", part1);
+
+#part 2
+
+SimTime2 = 1000000000; #minutes for part2
+values = {};
+prev = 0;
+
+CurrentState = InitialState.copy();
+for t in range(1,SimTime2):
+ NextState = {};
+ for x in range(size):
+ for y in range(size):
+ NextState.update({(x,y):ChangeState(CurrentState,(x,y))});
+ CurrentState = NextState.copy();
+ summary = list(CurrentState.values());
+ woods = summary.count("|");
+ lumbs = summary.count("#");
+ part2 = woods*lumbs;
+ loop = t - values.get(part2,0);
+ if (loop == prev):
+ if SimTime2%loop == t%loop:
+ break;
+ values[part2]=t;
+ prev = loop;
+
+print("part 2 = ", part2);
+