diff options
Diffstat (limited to '2018')
| -rw-r--r-- | 2018/aoc2018-d02.py | 43 | ||||
| -rw-r--r-- | 2018/aoc2018-d04.py (renamed from 2018/aoc2018-d04-1.py) | 93 | ||||
| -rw-r--r-- | 2018/aoc2018-d05-1.py | 60 | ||||
| -rw-r--r-- | 2018/aoc2018-d05-2.py | 72 | ||||
| -rw-r--r-- | 2018/aoc2018-d05.py | 64 | ||||
| -rwxr-xr-x | 2018/aoc2018-d07-1.py | 116 | ||||
| -rwxr-xr-x | 2018/aoc2018-d07-2.py | 190 | ||||
| -rw-r--r-- | 2018/aoc2018-d07.py | 157 | ||||
| -rwxr-xr-x | 2018/aoc2018-d08-1.py | 31 | ||||
| -rwxr-xr-x | 2018/aoc2018-d08-2.py | 51 | ||||
| -rw-r--r-- | 2018/aoc2018-d08.py | 52 | ||||
| -rwxr-xr-x | 2018/aoc2018-d11-1.py | 75 | ||||
| -rw-r--r--[-rwxr-xr-x] | 2018/aoc2018-d11.py (renamed from 2018/aoc2018-d11-2.py) | 68 | ||||
| -rw-r--r-- | 2018/aoc2018-d15-1.py | 324 | ||||
| -rw-r--r-- | 2018/aoc2018-d15.py | 175 |
15 files changed, 563 insertions, 1008 deletions
diff --git a/2018/aoc2018-d02.py b/2018/aoc2018-d02.py new file mode 100644 index 0000000..7142537 --- /dev/null +++ b/2018/aoc2018-d02.py @@ -0,0 +1,43 @@ +#advent of code 2018 +#day 02 +#part 1 and 2 + +PuzzleInput = open("02.in","r"); +boxes = []; +for line in PuzzleInput: + line = line.replace("\n",""); + boxes.append(line); + +duplicates = dict(); +duplicates[2] = set(); +duplicates[3] = set(); +for box in boxes: + boxdict = dict.fromkeys(set(list(box)),0); + for bchar in boxdict: + boxdict[bchar] = box.count(bchar); + for num in [2,3]: + if num in boxdict.values(): + duplicates[num].add(box); + +p1 = len(duplicates[3]) * len(duplicates[2]); +print("part 1 =", p1); + +visited = set(); +p2 = None; +for box1 in boxes: + for box2 in boxes: + if box1 == box2: continue; + if box2 in visited: continue; + matched = 0; + difference = set(); + for i in range(len(box1)): + if box1[i] != box2[i] : difference.add(box1[i]); + if len(difference) > 1: break; + if len(difference) == 1: + DifferentChar = difference.pop(); + p2 = box1.replace(DifferentChar,""); + break; + if p2: break; + visited.add(box1); + +print("part 2 =", p2); diff --git a/2018/aoc2018-d04-1.py b/2018/aoc2018-d04.py index 6f28be5..42791fd 100644 --- a/2018/aoc2018-d04-1.py +++ b/2018/aoc2018-d04.py @@ -1,5 +1,8 @@ -import numpy as np +#advent of code 2018 +#day 04 +#part 1 and 2 +import numpy as np def datecompact(log): d = log[1:5] + log[6:8] + log[9:11] + log[12:14] + log[15:17]; @@ -11,19 +14,15 @@ def action(log): elif (log[19] == "w"): return 2; else: - #return 3; return int(log[24:].strip("\n # begins shift")); return (log[24:].strip("\n # begins shift")); - #return int(log[24:].strip("#beginshft\n")); -f = open("input"); -#f = open("testinput"); +f = open("04.in","r"); myinput = []; guards = {}; for i in f: - #print(datecompact(i)); myinput.append([datecompact(i),action(i)]); if (action(i) != 1 and action(i) != 2 ): try: @@ -31,27 +30,14 @@ for i in f: except: True; - for i in range(len(myinput)): - #print(i[0], " -- ", i[1]); for j in range(len(myinput)): if (myinput[i][0] < myinput[j][0]): temp = myinput[i]; myinput[i] = myinput[j]; myinput[j] = temp; - -#print(guards); - -#for i in range(len(myinput) -1): - #if (myinput[i][0] > myinput[i+1][0]): - #print("fuck"); -#for i in myinput: -# print(i[0], " -- ", i[1]); - x1 = 0; - - for l in myinput: if l[1] == 2: guards[g] += l[0] - x1 ; @@ -59,41 +45,19 @@ for l in myinput: x1 = l[0]; else: g = l[1]; - tmax = 0; bestg = ""; for g in guards.keys(): - print(g); - #''' if (guards[g] >tmax): tmax = guards[g]; bestg = g; - #''' - -print("best guard ",bestg," - ", tmax); -#part1 = int(bestg)*tmax; -#print("part1", part1); - -#269357 too high -#256332 too high - - is_bestg = False; - -#timestat = np.array(60); -#timestat.fill(0); timestat = np.full(60,0, dtype=int); - -#bestg = int(bestg); - for l in myinput: - print("iterating", l[0], " ", l[1], " ", l[0]%100); - if (is_bestg and (l[1] == 1 or l[1] == 2)): - print("yup"); if l[1] == 1: t1 = l[0]; elif l[1] == 2: @@ -103,21 +67,38 @@ for l in myinput: elif l[1] == bestg: is_bestg = True; elif l[1] != bestg: - print("not bestg"); is_bestg = False; - -''' - guards[g] += l[0] - x1 ; - elif l[1] == 1: - x1 = l[0]; - else: - g = l[1]; -''' worsttime = (np.argmax(timestat)); - -part1 = int(bestg)*worsttime; - - -print("best guard ",bestg," - ", worsttime); -print("part1", part1); +p1 = int(bestg)*worsttime; +print("part 1 =",p1); + +GuardsTimestamps = dict(); +for l in sorted(myinput, key = lambda ts: ts[0]): + g_ts, t_code = l; + if t_code == 1: + SleepStart = 0 + g_ts; + elif t_code == 2: + SleepEnd = 0 + g_ts; + for minute in range(SleepStart%100, SleepEnd%100 + 1): + if minute not in GuardsTimestamps[CurrentGuard]: + GuardsTimestamps[CurrentGuard][minute] = 0; + GuardsTimestamps[CurrentGuard][minute] += 1; + else: + CurrentGuard = 0 + t_code; + if CurrentGuard not in GuardsTimestamps: + GuardsTimestamps[CurrentGuard] = dict(); + +SleepFrequency = []; +for Guard in GuardsTimestamps: + BestMinute = 0; + BestMinuteFreq = 0; + for ts in GuardsTimestamps[Guard]: + if GuardsTimestamps[Guard][ts] > BestMinuteFreq: + BestMinuteFreq = GuardsTimestamps[Guard][ts]; + BestMinute = ts; + SleepFrequency.append((Guard,BestMinute,BestMinuteFreq)); + +MostFrequent = max(SleepFrequency, key = lambda sf: sf[2]); +p2 = MostFrequent[0]*MostFrequent[1]; +print("part 2 =",p2); diff --git a/2018/aoc2018-d05-1.py b/2018/aoc2018-d05-1.py deleted file mode 100644 index b1d8ebc..0000000 --- a/2018/aoc2018-d05-1.py +++ /dev/null @@ -1,60 +0,0 @@ - -f = open("input"); -#f = open("testinput"); - -''' -test1 = ord("a") - ord("A"); -test2 = ord("b") - ord("B"); -test3 = ord("c") - ord("C"); - -print(test1, " ",test2, " ",test3, " ") - -''' - -cdiff = 32; - -def polymer_d(a,b): - return (cdiff == abs(ord(a) - ord(b))); - - -myinput = f.read(); -print(myinput); -print(len(myinput)); - -is_poly = True; -''' -while is_poly: - is_poly = False; - for x in range(1,len(myinput)): - x1 = myinput[x-1]; - x2 = myinput[x]; - if polymer_d(x1,x2): - #print((x1+x2)); - #myinput = myinput.replace((x1+x2),""); - myinput = myinput[ - is_poly = True; - break; - #is_poly = False; -''' - -while is_poly: - is_poly = False; - sub = ""; - for x in range(2,len(myinput)): - - x1 = myinput[x-2]; - x2 = myinput[x-1]; - if polymer_d(x1,x2): - myinput = sub + myinput[x:]; - is_poly = True; - break; - else: - sub += x1; -#print(myinput); -print(len(myinput)); -print(myinput); -myinput.rstrip("\n"); - -print("part 1", len(myinput) -1); -#9687 too high -#minus 1 helped lol, not sure why diff --git a/2018/aoc2018-d05-2.py b/2018/aoc2018-d05-2.py deleted file mode 100644 index be01aa0..0000000 --- a/2018/aoc2018-d05-2.py +++ /dev/null @@ -1,72 +0,0 @@ - -f = open("input"); -#f = open("testinput"); - -''' -test1 = ord("a") - ord("A"); -test2 = ord("b") - ord("B"); -test3 = ord("c") - ord("C"); - -print(test1, " ",test2, " ",test3, " ") - -''' - -cdiff = 32; - -def polymer_d(a,b): - return (cdiff == abs(ord(a) - ord(b))); -''' -def polymer_strip(inp): - is_poly = True; - while is_poly: - is_poly = False; - sub = ""; - for x in range(2,len(inp)): - - x1 = inp[x-2]; - x2 = inp[x-1]; - if polymer_d(x1,x2): - inp = sub + inp[x:]; - is_poly = True; - break; - else: - sub += x1; - return inp; -''' -def polymer_strip(inp): - is_poly = True; - while is_poly: - is_poly = False; - for x in range(1,len(inp)): - x1 = inp[x-1]; - x2 = inp[x]; - if polymer_d(x1,x2): - #print((x1+x2)); - inp = inp.replace((x1+x2),""); - #myinput = myinput[ - is_poly = True; - break; - return inp; - #is_poly = False; - -myinput = f.read(); - -#print("A", ord("A"), "Z", ord("Z")); - -inp_max = 999999; -inp_c = ""; - -for c in range(ord("A"),ord("Z")+1,1): - #print(chr(c)); - subinput = myinput; - subinput = subinput.replace(chr(c),""); - subinput = subinput.replace(chr(c+cdiff),""); - subinput = polymer_strip(subinput); - if (len(subinput) < inp_max): - inp_max = len(subinput); - inp_c = c; - -print("part 2 ",inp_max -1); - -#again, needed minus 1 on answer -#not sure why is that but it works diff --git a/2018/aoc2018-d05.py b/2018/aoc2018-d05.py new file mode 100644 index 0000000..6ebd839 --- /dev/null +++ b/2018/aoc2018-d05.py @@ -0,0 +1,64 @@ +#advent of code 2018 +#day 05 +#part 1 and 2 + +#extremely slow, rewrite candidate + +def polymer_d(a,b): + return (cdiff == abs(ord(a) - ord(b))); + +def polymer_strip(inp): + is_poly = True; + while is_poly: + is_poly = False; + for x in range(1,len(inp)): + x1 = inp[x-1]; + x2 = inp[x]; + if polymer_d(x1,x2): + #print((x1+x2)); + inp = inp.replace((x1+x2),""); + #myinput = myinput[ + is_poly = True; + break; + return inp; + +#part1 +def PolymerReaction(myinput): + is_poly = True; + while is_poly: + is_poly = False; + sub = ""; + for x in range(2,len(myinput)): + x1 = myinput[x-2]; + x2 = myinput[x-1]; + if polymer_d(x1,x2): + myinput = sub + myinput[x:]; + is_poly = True; + break; + else: + sub += x1; + return len(myinput); + +#part 2 +def ShortestPolymer(myinput): + inp_max = 999999; + inp_c = ""; + for c in range(ord("A"),ord("Z")+1,1): + subinput = myinput; + subinput = subinput.replace(chr(c),""); + subinput = subinput.replace(chr(c+cdiff),""); + subinput = polymer_strip(subinput); + if (len(subinput) < inp_max): + inp_max = len(subinput); + inp_c = c; + return inp_max + +f = open("05.in","r"); +cdiff = 32; +PuzzleInput = f.read().replace("\n",""); +f.close(); +p1 = PolymerReaction(""+PuzzleInput); +print("part 1", p1); +p2 = ShortestPolymer(""+PuzzleInput); +print("part 2 ",p2); + diff --git a/2018/aoc2018-d07-1.py b/2018/aoc2018-d07-1.py deleted file mode 100755 index b734e18..0000000 --- a/2018/aoc2018-d07-1.py +++ /dev/null @@ -1,116 +0,0 @@ -#class step:
-# def __init__(self, name, unlocks):
-# self.name = name;
-# self.unlocks = unlocks;
-
-
-def TransInstr (instruction):
- return [instruction[5], instruction[36]];
-
-
-myinput = {};
-
-currentfilename = "input.txt";
-#currentfilename = "testinput.txt";
-
-f = open(currentfilename, 'r');
-
-#list1 = [];
-#list2 = {};
-list2 = set();
-
-for line in f:
- nowinstr = TransInstr(line);
- #myinput[nowinstr[1]].append(nowinstr[0]);
- list2.add(nowinstr[0]);
-
-#'''
- try:
- myinput[nowinstr[1]].append(nowinstr[0]);
- #myinput[nowinstr[1]] = nowinstr[0];
- except:
- myinput[nowinstr[1]] = [];
- myinput[nowinstr[1]].append(nowinstr[0]);
-#'''
-
-print(myinput.keys());
-print("##############");
-print(list2);
-print("##############");
-
-pr1 = list(myinput.keys());
-pr1.sort();
-pr2 = list(list2);
-pr2.sort();
-print(pr1);
-print(pr2);
-print("##############");
-
-print("##############");
-print("finding the first step");
-
-CurrentStep = '';
-
-AvailableSteps = [];
-#AvailableSteps.append(CurrentStep);
-
-for l in list2:
- IsUnique = True;
- for k in myinput.keys():
- #print("L ", l, "\tK ",k, "\t",l == k);
- if (l == k):
- IsUnique = False;
- break;
- if IsUnique:
- #CurrentStep = l;
- #break;
- AvailableSteps.append(l);
-
-print("Unique values are ", AvailableSteps);
-
-print("##############");
-print(myinput);
-print("##############");
-part1 = ""; #CurrentStep;
-
-#list1 = myinput.keys();
-#list1.append(CurrentStep);
-#print(list1);
-
-
-while (len(AvailableSteps) != 0):
- #input();
- AvailableSteps.sort();
- CurrentStep = AvailableSteps[0];
- part1 += CurrentStep;
- print("now ", CurrentStep);
- for step in myinput:
- #x = myinput[step].index(CurrentStep);
- #print(x, "\t",myinput[step]);
- #myinput[step].pop(0);
- #print(x, "\t",myinput[step]);
- try:
- #print("try worked");
- myinput[step].pop(myinput[step].index(CurrentStep));
- except:
- #print("skip");
- pass;
- if (len(myinput[step]) == 0 and part1.find(step) == -1):
- AvailableSteps.append(step);
-
- AvailableSteps.pop(0);
-
-print("##################################");
-
-def RemoveDupsOrder(TheString):
- a = "";
- for letter in TheString:
- if not (letter in a):
- a += letter;
- return a;
-
-print(part1);
-
-part1 = RemoveDupsOrder(part1);
-
-print(part1);
diff --git a/2018/aoc2018-d07-2.py b/2018/aoc2018-d07-2.py deleted file mode 100755 index 2196e47..0000000 --- a/2018/aoc2018-d07-2.py +++ /dev/null @@ -1,190 +0,0 @@ -class elf:
- #HasWork = False;
- #WorkTime = 0;
- #WorkStep = '';
-
- def WorkAssign(self,s):
- AocOffset = 60; #correct value
- #AocOffset = 0; #example only
- self.WorkStep = s;
- self.WorkTime = ord(s) -64 + AocOffset;
- self.HasWork = True;
-
- def WorkReset(self):
- self.HasWork = False;
- #self.WorkTime = 0;
- self.WorkStep = '';
- def DoWork(self):
- self.WorkTime += -1;
- #if
- # return
- def __init__(self):#, name, unlocks):
- self.HasWork = False;
- self.WorkTime = 1;
- self.WorkStep = '';
-
- def __str__(self):
- return f"{self.WorkStep}\t{self.WorkTime}\t{self.HasWork}";
-
-def WorkInProgress(elflist):
- w = False;
- for e in elflist:
- w += e.HasWork;
- return w;
-
-def TransInstr (instruction):
- return [instruction[5], instruction[36]];
-
-
-myinput = {};
-
-currentfilename = "input.txt";
-numberofworkers = 5;
-#currentfilename = "testinput.txt"; #example only
-#numberofworkers = 2;#example only
-
-f = open(currentfilename, 'r');
-
-#list1 = [];
-#list2 = {};
-list2 = set();
-
-for line in f:
- nowinstr = TransInstr(line);
- #myinput[nowinstr[1]].append(nowinstr[0]);
- list2.add(nowinstr[0]);
-
-#'''
- try:
- myinput[nowinstr[1]].append(nowinstr[0]);
- #myinput[nowinstr[1]] = nowinstr[0];
- except:
- myinput[nowinstr[1]] = [];
- myinput[nowinstr[1]].append(nowinstr[0]);
-#'''
-
-print(myinput.keys());
-print("##############");
-print(list2);
-print("##############");
-
-pr1 = list(myinput.keys());
-pr1.sort();
-pr2 = list(list2);
-pr2.sort();
-print(pr1);
-print(pr2);
-print("##############");
-
-print("##############");
-print("finding the first step");
-
-CurrentStep = '';
-
-workers = [];
-
-for i in range(numberofworkers):
- workers.append(elf());
-
-
-AvailableSteps = [];
-#AvailableSteps.append(CurrentStep);
-
-for l in list2:
- IsUnique = True;
- for k in myinput.keys():
- #print("L ", l, "\tK ",k, "\t",l == k);
- if (l == k):
- IsUnique = False;
- break;
- if IsUnique:
- #CurrentStep = l;
- #break;
- AvailableSteps.append(l);
-
-print("Unique values are ", AvailableSteps);
-
-print("##############");
-print(myinput);
-print("##############");
-part1 = ""; #CurrentStep;
-
-#list1 = myinput.keys();
-#list1.append(CurrentStep);
-#print(list1);
-part2 = -1;
-IsWork = False;
-print("whileloop begins");
-while (len(AvailableSteps) != 0 or IsWork):
-
- part2 += 1;#input();
- #IsWork = False;
- AvailableSteps.sort();
- #CurrentStep = AvailableSteps[0];
- print(part2, " - steps sorted:",AvailableSteps);
- for worker in workers:
- #print(worker);
- #print(worker.WorkTime);
- worker.DoWork();
- if (worker.WorkTime == 0): # and worker.WorkStep != ''):
- part1 += worker.WorkStep;
- #if (worker.WorkSte
- if (worker.WorkStep != ''):
- for step in myinput:
- try:
- myinput[step].pop(myinput[step].index(worker.WorkStep));
- except:
- pass;
- CurrentStepsCheck = "";# workers[0].WorkStep + workers[1].WorkStep + workers[2].WorkStep + workers[3].WorkStep;
- for w in workers:
- CurrentStepsCheck += w.WorkStep;
- if (len(myinput[step]) == 0 and part1.find(step) == -1 and CurrentStepsCheck.find(step) == -1 ): #and AvailableSteps.find(step) == -1):
- AvailableSteps.append(step);
- worker.WorkReset();
- #worker.WorkStep() = '';
- #worker.HasWork() = False;
- AvailableSteps = list(dict.fromkeys(AvailableSteps));
-
- for worker in workers:
- if not worker.HasWork:
- if (len(AvailableSteps) > 0):
- worker.WorkAssign(AvailableSteps[0]);
- print("\tWorker begins step", AvailableSteps[0], "at second ", part2);
- AvailableSteps.pop(0);
- #else:
- #worker.DoWork();
- #worker.WorkTime() += -1;
-
- #part1 += CurrentStep;
- #print("now ", CurrentStep);
- '''
- for step in myinput:
- try:
- myinput[step].pop(myinput[step].index(CurrentStep));
- except:
- pass;
- if (len(myinput[step]) == 0 and part1.find(step) == -1): #and AvailableSteps.find(step) == -1):
- AvailableSteps.append(step);
- '''
-
- IsWork = WorkInProgress(workers);
- #AvailableSteps.pop(0);
-
-print("whileloop finished");
-print("##################################");
-
-def RemoveDupsOrder(TheString):
- a = "";
- for letter in TheString:
- if not (letter in a):
- a += letter;
- return a;
-
-print(part1);
-
-part1 = RemoveDupsOrder(part1);
-
-print(part1);
-print("total time part2 = ", part2);
-#207 too low (because I forgot to add 60secs per step, fixed now
-#987 correct
diff --git a/2018/aoc2018-d07.py b/2018/aoc2018-d07.py new file mode 100644 index 0000000..e7de018 --- /dev/null +++ b/2018/aoc2018-d07.py @@ -0,0 +1,157 @@ +#advent of code 2018
+#day 07
+#part 1 and 2
+
+#very bad don't read
+#I had solutions for both parts in separate files
+#so I slapped a def function above all code with filename as an argument
+class elf:
+ def WorkAssign(self,s):
+ AocOffset = 60;
+ self.WorkStep = s;
+ self.WorkTime = ord(s) -64 + AocOffset;
+ self.HasWork = True;
+
+ def WorkReset(self):
+ self.HasWork = False;
+ self.WorkStep = '';
+ def DoWork(self):
+ self.WorkTime += -1;
+
+ def __init__(self):
+ self.HasWork = False;
+ self.WorkTime = 1;
+ self.WorkStep = '';
+
+ def __str__(self):
+ return f"{self.WorkStep}\t{self.WorkTime}\t{self.HasWork}";
+
+
+def WorkInProgress(elflist):
+ w = False;
+ for e in elflist:
+ w += e.HasWork;
+ return w;
+
+def TransInstr (instruction):
+ return [instruction[5], instruction[36]];
+
+
+def RemoveDupsOrder(TheString):
+ a = "";
+ for letter in TheString:
+ if not (letter in a):
+ a += letter;
+ return a;
+
+#part 2
+def WorkTime(currentfilename):
+ myinput = {};
+ numberofworkers = 5;
+ f = open(currentfilename, 'r');
+ list2 = set();
+ for line in f:
+ nowinstr = TransInstr(line);
+ list2.add(nowinstr[0]);
+ try:
+ myinput[nowinstr[1]].append(nowinstr[0]);
+ except:
+ myinput[nowinstr[1]] = [];
+ myinput[nowinstr[1]].append(nowinstr[0]);
+ f.close();
+
+ CurrentStep = '';
+ workers = [];
+ for i in range(numberofworkers):
+ workers.append(elf());
+
+ AvailableSteps = [];
+ for l in list2:
+ IsUnique = True;
+ for k in myinput.keys():
+ if (l == k):
+ IsUnique = False;
+ break;
+ if IsUnique:
+ AvailableSteps.append(l);
+
+ part1 = "";
+ part2 = -1;
+ IsWork = False;
+ while (len(AvailableSteps) != 0 or IsWork):
+ part2 += 1;
+ AvailableSteps.sort();
+ for worker in workers:
+ worker.DoWork();
+ if (worker.WorkTime == 0):
+ part1 += worker.WorkStep;
+ if (worker.WorkStep != ''):
+ for step in myinput:
+ try:
+ myinput[step].pop(myinput[step].index(worker.WorkStep));
+ except:
+ pass;
+ CurrentStepsCheck = "";
+ for w in workers:
+ CurrentStepsCheck += w.WorkStep;
+ if (len(myinput[step]) == 0 and part1.find(step) == -1 and CurrentStepsCheck.find(step) == -1 ):
+ AvailableSteps.append(step);
+ worker.WorkReset();
+ AvailableSteps = list(dict.fromkeys(AvailableSteps));
+ for worker in workers:
+ if not worker.HasWork:
+ if (len(AvailableSteps) > 0):
+ worker.WorkAssign(AvailableSteps[0]);
+ AvailableSteps.pop(0);
+ IsWork = WorkInProgress(workers);
+
+ return part2;
+
+#part 1
+def InstructionsOrder(currentfilename):
+ myinput = {};
+ f = open(currentfilename, 'r');
+ list2 = set();
+
+ for line in f:
+ nowinstr = TransInstr(line);
+ list2.add(nowinstr[0]);
+ try:
+ myinput[nowinstr[1]].append(nowinstr[0]);
+ except:
+ myinput[nowinstr[1]] = [];
+ myinput[nowinstr[1]].append(nowinstr[0]);
+
+ f.close();
+ CurrentStep = '';
+ AvailableSteps = [];
+ for l in list2:
+ IsUnique = True;
+ for k in myinput.keys():
+ if (l == k):
+ IsUnique = False;
+ break;
+ if IsUnique:
+ AvailableSteps.append(l);
+ part1 = "";
+ while (len(AvailableSteps) != 0):
+ AvailableSteps.sort();
+ CurrentStep = AvailableSteps[0];
+ part1 += CurrentStep;
+ for step in myinput:
+ try:
+ myinput[step].pop(myinput[step].index(CurrentStep));
+ except:
+ pass;
+ if (len(myinput[step]) == 0 and part1.find(step) == -1):
+ AvailableSteps.append(step);
+ AvailableSteps.pop(0);
+
+ return part1;
+
+myfilename = "07.in";
+p1 = InstructionsOrder(myfilename);
+p1 = RemoveDupsOrder(p1);
+print("part 1 =",p1);
+p2 = WorkTime(myfilename);
+print("part 2 =", p2);
diff --git a/2018/aoc2018-d08-1.py b/2018/aoc2018-d08-1.py deleted file mode 100755 index 2d0110d..0000000 --- a/2018/aoc2018-d08-1.py +++ /dev/null @@ -1,31 +0,0 @@ -currentfilename = "input.txt";
-#currentfilename = "testinput.txt"; #example only
-
-f = open(currentfilename, 'r');
-myinput = eval(f.read().replace(" ",","));
-f.close();
-
-#for i in myinput:
-# print(i);
-
-def NodeAnalysis(License, index):
- NumberOfChilds = License[index[0]];
- index[0] += 1;
- NumberofEntries = License[index[0]];
- index[0] += 1;
- #print(index, " - this node has ", NumberOfChilds, " and ", NumberofEntries);
- for child in range(NumberOfChilds):
- NodeAnalysis(License, index);
-
- for entry in range(NumberofEntries):
- index[1] += License[index[0]];
- index[0] += 1;
- #print("\tcurrent index ", index[0]);
-
-
-i = [0,0];
-
-NodeAnalysis(myinput, i);
-print("input length\t", len(myinput));
-print("final index\t", i[0]);
-print("part1 answer\t", i[1]);
diff --git a/2018/aoc2018-d08-2.py b/2018/aoc2018-d08-2.py deleted file mode 100755 index 17ce2cc..0000000 --- a/2018/aoc2018-d08-2.py +++ /dev/null @@ -1,51 +0,0 @@ -currentfilename = "input.txt";
-#currentfilename = "testinput.txt"; #example only
-
-f = open(currentfilename, 'r');
-myinput = eval(f.read().replace(" ",","));
-f.close();
-
-#for i in myinput:
-# print(i);
-
-def NodeAnalysis(License, index):
- NodeVal = 0;
- NumberOfChilds = License[index[0]];
- index[0] += 1;
- NumberofEntries = License[index[0]];
- index[0] += 1;
- print(index, " - this node has ", NumberOfChilds, " and ", NumberofEntries);
- ListOfEntries = [];
- ListOfChilds = [];
- for child in range(NumberOfChilds):
- ListOfChilds.append(NodeAnalysis(License, index));
-
-
- for entry in range(NumberofEntries):
- ListOfEntries.append(License[index[0]]);
- #index[1] += License[index[0]];
- index[0] += 1;
- #print("\tcurrent index ", index[0]);
- if(NumberOfChilds == 0):
- NodeVal = sum(ListOfEntries);
- #for entry in range(NumberofEntries):
- # NodeVal += License[index[0]];
- # index[0] += 1;
- else:
- for e in ListOfEntries:
- if (e == 0 or e >NumberOfChilds):
- continue;
- NodeVal+= ListOfChilds[e-1];
- print("now ", NodeVal);
- index.append(NodeVal);
- return NodeVal;
-
-
-i = [0,0];
-
-part2 = NodeAnalysis(myinput, i);
-print("input length\t", len(myinput));
-print("final index\t", i[0]);
-print("part1 answer\t", i[1]);
-print("part2 answer\t", i[1]);
-print("part2 answer\t", i[-1]);
diff --git a/2018/aoc2018-d08.py b/2018/aoc2018-d08.py new file mode 100644 index 0000000..0dc174a --- /dev/null +++ b/2018/aoc2018-d08.py @@ -0,0 +1,52 @@ +#advent of code 2018
+#day 08
+#part 1 and 2
+
+
+f = open("08.in", 'r');
+myinput = eval(f.read().replace(" ",","));
+f.close();
+
+#part 1
+def NodeAnalysis_1(License, index):
+ NumberOfChilds = License[index[0]];
+ index[0] += 1;
+ NumberofEntries = License[index[0]];
+ index[0] += 1;
+ for child in range(NumberOfChilds):
+ NodeAnalysis_1(License, index);
+ for entry in range(NumberofEntries):
+ index[1] += License[index[0]];
+ index[0] += 1;
+
+#part 2
+def NodeAnalysis_2(License, index):
+ NodeVal = 0;
+ NumberOfChilds = License[index[0]];
+ index[0] += 1;
+ NumberofEntries = License[index[0]];
+ index[0] += 1;
+ ListOfEntries = [];
+ ListOfChilds = [];
+ for child in range(NumberOfChilds):
+ ListOfChilds.append(NodeAnalysis_2(License, index));
+
+ for entry in range(NumberofEntries):
+ ListOfEntries.append(License[index[0]]);
+ index[0] += 1;
+ if(NumberOfChilds == 0):
+ NodeVal = sum(ListOfEntries);
+ else:
+ for e in ListOfEntries:
+ if (e == 0 or e >NumberOfChilds):
+ continue;
+ NodeVal+= ListOfChilds[e-1];
+ index.append(NodeVal);
+ return NodeVal;
+
+i = [0,0];
+
+NodeAnalysis_1(myinput, i);
+print("part 1 =", i[-1]);
+part2 = NodeAnalysis_2(myinput, [0,0]);
+print("part 2 =", part2);
diff --git a/2018/aoc2018-d11-1.py b/2018/aoc2018-d11-1.py deleted file mode 100755 index 2379c3c..0000000 --- a/2018/aoc2018-d11-1.py +++ /dev/null @@ -1,75 +0,0 @@ -#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-2.py b/2018/aoc2018-d11.py index dbfafe7..442f373 100755..100644 --- a/2018/aoc2018-d11-2.py +++ b/2018/aoc2018-d11.py @@ -1,17 +1,15 @@ #advent of code 2018
#day 11
-#part 2
-#too lazy to clean up the code, might do it later (i.e. never)
+#part 1 and 2
+#at this point it would probably be faster to rewrite the solution
+#instead of trying to merge both parts bc i have no clue whats going on
+#maybe someday
#setup
GridSize = 300;
SquareSize = 3;
-fcserialnumber = int(open("input.txt",'r').readline());
+fcserialnumber = int(open("11.in",'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):
@@ -25,35 +23,47 @@ class fuelcell: self.powerlevel = self.powerlevel%10;
self.powerlevel -= 5;
def coords(self):
- print(f'Fuel Cell coordinates (x,y): {self.positionX},{self.positionY} ');
+ #print(f'Fuel Cell coordinates (x,y): {self.positionX},{self.positionY} ');
+ return f'{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");
+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("part 1 =",fcgrid[maxY][maxX].coords());
+
+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());
+
sumtable = [];
gridline.clear();
@@ -76,9 +86,6 @@ for Y in range(1,GridSize): gridline.append(sumtable[Y-1][X] + currentsubsum);
sumtable.append(gridline.copy());
-print("#############################");
-print("SEARCH FOR HIGHEST SUBSUM SQUARE");
-
maxpower = -999;
maxX = 0;
maxY = 0;
@@ -98,11 +105,6 @@ for Y in range(1,GridSize-3): 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="");
+print("part 2 =", f'{fcgrid[maxY][maxX].positionX},{fcgrid[maxY][maxX].positionY},{maxsquare+1}')#,end="");
diff --git a/2018/aoc2018-d15-1.py b/2018/aoc2018-d15-1.py deleted file mode 100644 index 6a2665d..0000000 --- a/2018/aoc2018-d15-1.py +++ /dev/null @@ -1,324 +0,0 @@ -#advent of code 2018 -#day 13 -#part 1 -import heapq - -f = open("input.txt",'r'); -Testing = False; -Testing = True; -if Testing: - f.close(); - f = open("testinput.txt",'r'); -Testing2 = False; -Testing2 = True; -if Testing2: - f.close(); - f = open("testinput2.txt",'r'); -Testing3 = False; -#Testing3 = True; -if Testing3: - f.close(); - f = open("testinput3.txt",'r'); -Testing4 = False; -#Testing4 = True; -if Testing4: - f.close(); - f = open("testinput4.txt",'r'); -Testing5 = False; -Testing5 = True; -if Testing5: - f.close(); - f = open("testinput5.txt",'r'); -Testing6 = False; -Testing6 = True; -if Testing6: - f.close(); - f = open("testinput6.txt",'r'); -Testing7 = False; -Testing7 = True; -if Testing7: - f.close(); - f = open("testinput7.txt",'r'); -NotTesting = False; -NotTesting = True; -if NotTesting: - f.close(); - f = open("input.txt",'r'); - #f = open("shit.txt",'r'); - -class thing: - def __init__(self, Pos, sign, currentID): - self.sign = sign; - self.PosX = Pos[1]; - self.PosY = Pos[0]; - self.IsAlive = False; - if (sign == "."): - self.IsPassable = True; - else: - self.IsPassable = False; - def __str__(self): - return self.sign; - - def SquaresInRange(self,bg): - squares = []; - p = (self.PosY-1,self.PosX); - if(bg[p].IsPassable): squares.append(p); - p = (self.PosY,self.PosX-1); - if(bg[p].IsPassable): squares.append(p); - p = (self.PosY,self.PosX+1); - if(bg[p].IsPassable): squares.append(p); - p = (self.PosY+1,self.PosX); - if(bg[p].IsPassable): squares.append(p); - return squares; - -class creature(thing): - def __init__(self, Pos, sign, currentID): - thing.__init__(self, Pos, sign, currentID); - self.ID = currentID; - self.health = 200; - self.damage = 3; - self.side = sign; - self.IsAlive = True; - if (self.side == "G"): - self.enemy = "E"; - if (self.side == "E"): - self.enemy = "G"; - - def death(self,bg): - self.IsPassable = True; - self.IsAlive = False; - self.health = 0; - unitcords[(self.PosY,self.PosX)] = None; - bg[(self.PosY,self.PosX)].IsPassable = True; - - - def movement(self,bg,PosNow,PosNew): - self.PosX = PosNew[1]; - self.PosY = PosNew[0]; - bg[PosNow].IsPassable = True; - bg[PosNew].IsPassable = False; - unitcords[PosNew] = self.ID; - unitcords[PosNow] = None; - - - def ScanProximity(self): - targets = []; - p = (self.PosY-1,self.PosX); - if p in unitcords and unitcords[p] in units and units[unitcords[p]].side == self.enemy and units[unitcords[p]].health >0: - targets.append(p); - p = (self.PosY,self.PosX-1); - if p in unitcords and unitcords[p] in units and units[unitcords[p]].side == self.enemy and units[unitcords[p]].health >0: - targets.append(p); - p = (self.PosY,self.PosX+1); - if p in unitcords and unitcords[p] in units and units[unitcords[p]].side == self.enemy and units[unitcords[p]].health >0: - targets.append(p); - p = (self.PosY+1,self.PosX); - if p in unitcords and unitcords[p] in units and units[unitcords[p]].side == self.enemy and units[unitcords[p]].health >0: - targets.append(p); - if targets: - targets.sort(key = lambda x: (units[unitcords[x]].health,units[unitcords[x]].PosY,units[unitcords[x]].PosX)); - return targets; - - - def IdentifyTargets_ALL(self,creaturelist,bg): - points = []; - for c in creaturelist: - if units[c].side == self.side or not units[c].IsAlive: continue; - points.extend(units[c].SquaresInRange(bg)); - return points; - - - def ShortestPaths(self, pointlist, bg): - paths = []; - pathlen = len(bg); - queue = []; - heapq.heappush(queue, (0,[(self.PosY,self.PosX)])); - visited = []; - while queue: - d, path = heapq.heappop(queue); - if d > pathlen: - return paths; - if path[-1] in pointlist: - if pathlen > len(path): - paths.append(path); - pathlen = len(path); - continue; - if path[-1] in visited: - continue; - else: - visited.append(path[-1]); - for a in bg[path[-1]].SquaresInRange(bg): - if a in visited: continue; - heapq.heappush(queue, (d+1, path + [a])); - return paths; - - def ChosenPath(self, pointlist, bg): - paths = self.ShortestPaths(pointlist, bg); - if len(paths) != 0: - pathends = min([p[-1] for p in paths]); - paths2= self.ShortestPaths([pathends], bg); - if len(paths2) != 0: - moves = []; - for p in paths: - moves.append(p[1]); - moves = sorted(moves, key = lambda m: (m[0],m[1])); - m = moves[0]; - self.movement(bg,(self.PosY,self.PosX),m); - - -def PathSearch(bg, Coordinates, Destination): - pass; - -def strike(attacker, target,bg): - target.health -= attacker.damage; - if (target.health <= 0): - target.death(bg); - -def armystrength(army): - strength = 0; - for soldier in army: - strength += units[unitcords[soldier]].health; - return strength; - -def armyscores(): - ElfScore = 0; - GobScore = 0; - for u in units: - if units[u].side == "G": GobScore += units[u].health; - if units[u].side == "E": ElfScore += units[u].health; - - return max(ElfScore,GobScore); - - - -def FindEnemies(team): - Enemies = 0; - for u in units: - if units[u].IsAlive and units[u].side != team: Enemies += 1; - - return Enemies; -############################################################################### - - -bgsizex = 0; -bgsizey = 0; -battleground = {}; -units = {}; -unitcords = {}; - -identifier = 11; - -for y, line in enumerate(f): - bgsizey += 1; - bgsizex = 0; - for x, c in enumerate(line): - bgsizex += 1; - if c == "G" or c == "E": - battleground[(y,x)] = thing((y,x),".",identifier); - units[identifier] = creature((y,x),c, identifier); - units[identifier].movement(battleground, (y,x), (y,x)); - identifier += 1; - else: - battleground[(y,x)] = thing((y,x),c,identifier); -''' -for y in range(bgsizey): - for x in range(bgsizex): - if (y,x) in unitcords: - print("X",end=""); - else: - print(battleground[(y,x)],end=""); #''' - - -unitcords = {}; -for u in units: - unitcords[(units[u].PosY,units[u].PosX)] = units[u].ID; - - -elfs = sum([1 for x in units if units[x].IsAlive and units[x].side=="E"]); -goblins = sum([1 for x in units if units[x].IsAlive and units[x].side=="G"]); - -ElapsedRounds = 0; - - -while goblins and elfs: - fighters = []; - for u in units: - if units[u].IsAlive: - fighters.append(units[u].ID); - - fighters = sorted(fighters, key = lambda u: (units[u].PosY,units[u].PosX)); - - for fighter in fighters: - if not units[fighter].IsAlive: continue; - if FindEnemies(units[fighter].side) <= 0: - print("loop broken FIGHTERS"); - break; - tars = units[fighter].ScanProximity(); - if tars: - tar = tars[0]; - strike(units[fighter],units[unitcords[tar]],battleground); - else: - CurrentPos = (units[fighter].PosY,units[fighter].PosX); - IdenTars = units[fighter].IdentifyTargets_ALL(fighters,battleground); - units[fighter].ChosenPath(IdenTars,battleground); - if CurrentPos == (units[fighter].PosY,units[fighter].PosX): - continue; - else: - tars = units[fighter].ScanProximity(); - if tars: - tar = tars[0]; - strike(units[fighter],units[unitcords[tar]],battleground); - - unitcords = {}; - for u in units: - unitcords[(units[u].PosY,units[u].PosX)] = units[u].ID; - - print("ROUND ", ElapsedRounds); - unitcords = {}; - for u in units: - unitcords[(units[u].PosY,units[u].PosX)] = units[u].ID; - - ElapsedRounds += 1; - elfs = sum([1 for x in units if units[x].IsAlive and units[x].side=="E"]); - goblins = sum([1 for x in units if units[x].IsAlive and units[x].side=="G"]); - ''' - for y in range(bgsizey): - for x in range(bgsizex): - if (y,x) in unitcords and unitcords[(y,x)] in units and units[unitcords[(y,x)]].IsAlive: - print(units[unitcords[(y,x)]].side,end=""); - else: - print(battleground[(y,x)],end=""); - print(); - ''' - - ''' - for y in range(bgsizey): - for x in range(bgsizex): - print((y,x), " - ", battleground[(y,x)].IsPassable); - print(); - print(); - ''' - - - -unitcords = {}; -for u in units: - unitcords[(units[u].PosY,units[u].PosX)] = units[u].ID; - print(u, f'({units[u].side} / ({units[u].PosY},{units[u].PosX})) ', units[u].health); - - -for y in range(bgsizey): - for x in range(bgsizex): - if (y,x) in unitcords and unitcords[(y,x)] in units and units[unitcords[(y,x)]].IsAlive: - print(units[unitcords[(y,x)]].side,end=""); - else: - print(battleground[(y,x)],end=""); -print(); - - -print("part 1 = ", ElapsedRounds, "*",armyscores(), "=",ElapsedRounds*armyscores()); -print("lil cheat = ", (ElapsedRounds-1), "*",armyscores(), "=",(ElapsedRounds-1)*armyscores()); -#I cant get the correct answer without implementing any short circuit logics -#thats why I print 2 outputs, for number of rounds and (number of rounds -1) - -#190777 p1 correct diff --git a/2018/aoc2018-d15.py b/2018/aoc2018-d15.py new file mode 100644 index 0000000..2911a4d --- /dev/null +++ b/2018/aoc2018-d15.py @@ -0,0 +1,175 @@ +#advent of code 2018 +#day 15 +#part 1 and 2 +#oop too hard for scriptkid + +import heapq + +class creature: + def __init__(self, pos, team, unitID,health,attack): + self.team = team; + self.pos = pos; + self.isAlive = True; + self.health = health; + self.attack = attack; + self.unitID = unitID; + + def __str__(self): + return f'{self.team} #{self.unitID}: {self.health}/200'; + + def GetAttacked(self,dmg): + self.health -= dmg; + if self.health <= 0: + self.isAlive = False; + self.health = 0; + + def LookAround(self,enemyset): + targets = []; + p0,p1 = self.pos; + for direction in ReadOrder: + neighbor = (p0+direction[0],p1+direction[1]); + if neighbor in enemyset: + targets.append(neighbor); + return targets; + + def pathfinding(self, enemyset, occupiedset): + paths = []; + pathlimit = len(grid); + queue = []; + heapq.heappush( queue,(0,[self.pos]) ); + visited = set(); + while queue: + d, path = heapq.heappop(queue); + if d > pathlimit: + return paths; + if path[-1] in enemyset: + if pathlimit >= len(path): + paths.append(path); + pathlimit = len(path); + continue; + if path[-1] in visited: continue; + visited.add(path[-1]); + p0,p1 = path[-1]; + for direction in ReadOrder: + neighbor = (p0+direction[0],p1+direction[1]); + if grid.get(neighbor,"#") != ".":continue; + if neighbor in occupiedset: continue; + heapq.heappush(queue,(d+1,path+[neighbor])); + return paths; + + def MakeMove(self, enemyset,occupiedset): + PossiblePaths = self.pathfinding(enemyset,occupiedset); + if len(PossiblePaths) != 0: + for nextpath in sorted( PossiblePaths, key = lambda node: node[1]): + self.pos = nextpath[1]; + return True; + break; + return False; + + +def run(ulist,att,part2): + units = dict(); + u_hp = 200; + for unit in ulist: + u_pos, u_team, u_id = unit; + u_att = 3; + if u_team == "E": u_att = att; + units[u_id] = creature(u_pos,u_team,u_id,u_hp,u_att) ; + + TotalHP = dict(); + TotalHP["E"] = 1; + TotalHP["G"] = 1; + Round = 0; + while TotalHP["E"] > 0 and TotalHP["G"] > 0: + if part2 and len([1 for uid in units if units[uid].isAlive==False and units[uid].team=="E"]) != 0: + return 0; + + for unit_id in sorted(units, key=lambda p: units[p].pos): + if not units[unit_id].isAlive : continue; + enemyLocation = dict(); + for Unit in units: + if units[Unit].team != units[unit_id].team and units[Unit].isAlive: + enemyLocation[units[Unit].pos] = Unit; + + occupied = set([units[Unit].pos for Unit in units if units[Unit].isAlive and units[Unit].team == units[unit_id].team]); + InRangeTargets = units[unit_id].LookAround(enemyLocation); + + if len(InRangeTargets) != 0: + TargetsOrdered = sorted([enemyLocation[tar] for tar in InRangeTargets], key = lambda en: (units[en].health,units[en].pos)); + targetEnemy = TargetsOrdered[0]; + units[targetEnemy].GetAttacked( units[unit_id].attack ); + continue; + + MadeMove = units[unit_id].MakeMove(enemyLocation,occupied); + if not MadeMove: continue; + InRangeTargets = units[unit_id].LookAround(enemyLocation); + if len(InRangeTargets) != 0: + TargetsOrdered = sorted([enemyLocation[tar] for tar in InRangeTargets], key = lambda en: (units[en].health,units[en].pos)); + targetEnemy = TargetsOrdered[0]; + units[targetEnemy].GetAttacked( units[unit_id].attack ); + + TotalHP["E"] = sum([units[uid].health for uid in units if units[uid].team=="E"]); + TotalHP["G"] = sum([units[uid].health for uid in units if units[uid].team=="G"]); + Round += 1; + ################### + #optional turn by turn battleground output + ''' + print(); + locations = dict(); + for unitprint in units: + if not units[unitprint].isAlive: + locations[ units[unitprint].pos ] = units[unitprint].team.casefold() ; + else: + locations[ units[unitprint].pos ] = units[unitprint].team ; + print(units[unitprint]); + + + print("Round",Round); + for y in range(bgsizeY+1): + for x in range(bgsizeX+1): + c = locations.get((y,x),grid[(y,x)]); + print(c,end=""); + print(); + #input(); + ''' + ################### + #part 2 requires all elves to be alive so it's a different check than in part 1 + if part2 and len([1 for u in units if units[u].isAlive==False and units[u].team=="E"]) != 0: + return 0; + else: + #"number of full rounds that were completed (not counting the round in which combat ends)" + elfscore = (Round-1)*sum([units[uid].health for uid in units if units[uid].team=="E"]); + gobscore = (Round-1)*sum([units[uid].health for uid in units if units[uid].team=="G"]); + return(max(elfscore,gobscore)); + + +bgsizeY = 0; +bgsizeX = 0; +grid = dict(); +unitlist = []; +ReadOrder = [(-1,0),(0,-1),(0,1),(1,0)]; +unit_counter = 0; +PuzzleInput = open("15.in","r"); +for y,l in enumerate(PuzzleInput): + l = l.replace("\n",""); + bgsizeY = max(bgsizeY,y); + for x, c in enumerate(l): + bgsizeX = max(bgsizeX,x); + if c == "#": + grid[(y,x)] = "#"; + elif c == ".": + grid[(y,x)] = "."; + else: + unitlist.append(((y,x),c,unit_counter)); + unit_counter += 1; + grid[(y,x)] = "."; +PuzzleInput.close(); + +AttackValue = 3; +p1 = run(unitlist,AttackValue,False); +print("part 1 =", p1); +p2 = 0; +while p2 == 0: + AttackValue += 1; + p2 = run(unitlist,AttackValue,True); +print("part 2 =", p2); |
