summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2018/aoc2018-d02.py43
-rw-r--r--2018/aoc2018-d04.py (renamed from 2018/aoc2018-d04-1.py)93
-rw-r--r--2018/aoc2018-d05-1.py60
-rw-r--r--2018/aoc2018-d05-2.py72
-rw-r--r--2018/aoc2018-d05.py64
-rwxr-xr-x2018/aoc2018-d07-1.py116
-rwxr-xr-x2018/aoc2018-d07-2.py190
-rw-r--r--2018/aoc2018-d07.py157
-rwxr-xr-x2018/aoc2018-d08-1.py31
-rwxr-xr-x2018/aoc2018-d08-2.py51
-rw-r--r--2018/aoc2018-d08.py52
-rwxr-xr-x2018/aoc2018-d11-1.py75
-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.py324
-rw-r--r--2018/aoc2018-d15.py175
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);