From f6ff66ea2da1f30303f17a2dac341411fb325881 Mon Sep 17 00:00:00 2001 From: blenovo Date: Sat, 16 Aug 2025 00:38:26 +0200 Subject: final puzzle and little cleanup for 2018 --- 2018/aoc2018-d02.py | 43 +++++++ 2018/aoc2018-d04-1.py | 123 ------------------- 2018/aoc2018-d04.py | 104 ++++++++++++++++ 2018/aoc2018-d05-1.py | 60 ---------- 2018/aoc2018-d05-2.py | 72 ----------- 2018/aoc2018-d05.py | 64 ++++++++++ 2018/aoc2018-d07-1.py | 116 ------------------ 2018/aoc2018-d07-2.py | 190 ----------------------------- 2018/aoc2018-d07.py | 157 ++++++++++++++++++++++++ 2018/aoc2018-d08-1.py | 31 ----- 2018/aoc2018-d08-2.py | 51 -------- 2018/aoc2018-d08.py | 52 ++++++++ 2018/aoc2018-d11-1.py | 75 ------------ 2018/aoc2018-d11-2.py | 108 ----------------- 2018/aoc2018-d11.py | 110 +++++++++++++++++ 2018/aoc2018-d15-1.py | 324 -------------------------------------------------- 2018/aoc2018-d15.py | 175 +++++++++++++++++++++++++++ 17 files changed, 705 insertions(+), 1150 deletions(-) create mode 100644 2018/aoc2018-d02.py delete mode 100644 2018/aoc2018-d04-1.py create mode 100644 2018/aoc2018-d04.py delete mode 100644 2018/aoc2018-d05-1.py delete mode 100644 2018/aoc2018-d05-2.py create mode 100644 2018/aoc2018-d05.py delete mode 100755 2018/aoc2018-d07-1.py delete mode 100755 2018/aoc2018-d07-2.py create mode 100644 2018/aoc2018-d07.py delete mode 100755 2018/aoc2018-d08-1.py delete mode 100755 2018/aoc2018-d08-2.py create mode 100644 2018/aoc2018-d08.py delete mode 100755 2018/aoc2018-d11-1.py delete mode 100755 2018/aoc2018-d11-2.py create mode 100644 2018/aoc2018-d11.py delete mode 100644 2018/aoc2018-d15-1.py create mode 100644 2018/aoc2018-d15.py (limited to '2018') 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-1.py deleted file mode 100644 index 6f28be5..0000000 --- a/2018/aoc2018-d04-1.py +++ /dev/null @@ -1,123 +0,0 @@ -import numpy as np - - -def datecompact(log): - d = log[1:5] + log[6:8] + log[9:11] + log[12:14] + log[15:17]; - return int(d); - -def action(log): - if (log[19] == "f"): - return 1; - 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"); - -myinput = []; -guards = {}; - -for i in f: - #print(datecompact(i)); - myinput.append([datecompact(i),action(i)]); - if (action(i) != 1 and action(i) != 2 ): - try: - guards[action(i)] = 0; - 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 ; - elif l[1] == 1: - 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: - t2 = l[0]; - for t in range(t1%100,t2%100,1): - timestat[t] += 1; - 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); diff --git a/2018/aoc2018-d04.py b/2018/aoc2018-d04.py new file mode 100644 index 0000000..42791fd --- /dev/null +++ b/2018/aoc2018-d04.py @@ -0,0 +1,104 @@ +#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]; + return int(d); + +def action(log): + if (log[19] == "f"): + return 1; + elif (log[19] == "w"): + return 2; + else: + return int(log[24:].strip("\n # begins shift")); + return (log[24:].strip("\n # begins shift")); + +f = open("04.in","r"); + +myinput = []; +guards = {}; + +for i in f: + myinput.append([datecompact(i),action(i)]); + if (action(i) != 1 and action(i) != 2 ): + try: + guards[action(i)] = 0; + except: + True; + +for i in range(len(myinput)): + for j in range(len(myinput)): + if (myinput[i][0] < myinput[j][0]): + temp = myinput[i]; + myinput[i] = myinput[j]; + myinput[j] = temp; + +x1 = 0; +for l in myinput: + if l[1] == 2: + guards[g] += l[0] - x1 ; + elif l[1] == 1: + x1 = l[0]; + else: + g = l[1]; + +tmax = 0; +bestg = ""; + +for g in guards.keys(): + if (guards[g] >tmax): + tmax = guards[g]; + bestg = g; + +is_bestg = False; +timestat = np.full(60,0, dtype=int); +for l in myinput: + if (is_bestg and (l[1] == 1 or l[1] == 2)): + if l[1] == 1: + t1 = l[0]; + elif l[1] == 2: + t2 = l[0]; + for t in range(t1%100,t2%100,1): + timestat[t] += 1; + elif l[1] == bestg: + is_bestg = True; + elif l[1] != bestg: + is_bestg = False; + +worsttime = (np.argmax(timestat)); +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-2.py deleted file mode 100755 index dbfafe7..0000000 --- a/2018/aoc2018-d11-2.py +++ /dev/null @@ -1,108 +0,0 @@ -#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 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-d11.py b/2018/aoc2018-d11.py new file mode 100644 index 0000000..442f373 --- /dev/null +++ b/2018/aoc2018-d11.py @@ -0,0 +1,110 @@ +#advent of code 2018 +#day 11 +#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("11.in",'r').readline()); + + +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} '); + return f'{self.positionX},{self.positionY}'; + def __str__(self): + return f'{self.powerlevel}'; + +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("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(); +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()); + +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 maxpower): + maxX = X; + maxY = Y; + maxpower = powernow; + maxsquare = s; + +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); -- cgit v1.2.3