summaryrefslogtreecommitdiff
path: root/2020
diff options
context:
space:
mode:
Diffstat (limited to '2020')
-rw-r--r--2020/aoc2020-d01-1.py1
-rw-r--r--2020/aoc2020-d01.py22
-rw-r--r--2020/aoc2020-d02.py22
-rw-r--r--2020/aoc2020-d03.py29
-rw-r--r--2020/aoc2020-d04.py42
-rw-r--r--2020/aoc2020-d05.py33
-rw-r--r--2020/aoc2020-d06.py22
-rw-r--r--2020/aoc2020-d07.py48
-rw-r--r--2020/aoc2020-d08.py93
-rw-r--r--2020/aoc2020-d09.py55
-rw-r--r--2020/aoc2020-d10.py39
11 files changed, 405 insertions, 1 deletions
diff --git a/2020/aoc2020-d01-1.py b/2020/aoc2020-d01-1.py
deleted file mode 100644
index 23d2abb..0000000
--- a/2020/aoc2020-d01-1.py
+++ /dev/null
@@ -1 +0,0 @@
-print("hello");
diff --git a/2020/aoc2020-d01.py b/2020/aoc2020-d01.py
new file mode 100644
index 0000000..84cca45
--- /dev/null
+++ b/2020/aoc2020-d01.py
@@ -0,0 +1,22 @@
+#advent of code 2020
+#day 01
+
+p1 = 0;
+p2 = 0;
+entries = [];
+PuzzleInput = open("01.in","r");
+for l in PuzzleInput: entries.append(int(l));
+PuzzleInput.close();
+for e1 in entries:
+ for e2 in entries:
+ if e1 + e2 == 2020:
+ p1 = e1*e2;
+ for e3 in entries:
+ if e1 + e2 + e3 == 2020:
+ p2 = e1*e2*e3;
+ break;
+ if p2: break;
+ if p1 and p2: break;
+
+print("part 1 =",p1);
+print("part 2 =",p2);
diff --git a/2020/aoc2020-d02.py b/2020/aoc2020-d02.py
new file mode 100644
index 0000000..9871373
--- /dev/null
+++ b/2020/aoc2020-d02.py
@@ -0,0 +1,22 @@
+#advent of code 2020
+#day 02
+
+p1 = 0;
+p2 = 0;
+PuzzleInput = open("02.in","r");
+for l in PuzzleInput:
+ rules, pwd = l.split(": ");
+ limits, letter = rules.split(" ");
+ lo, hi = limits.split("-");
+ check = pwd.count(letter);
+ if int(lo) <= check and int(hi) >= check:
+ p1 += 1;
+ v1 = pwd[int(lo)-1] == letter;
+ v2 = pwd[int(hi)-1] == letter;
+ v3 = v1 + v2;
+ v4 = v1 != v2;
+ if v3 and v4: p2 += 1;
+PuzzleInput.close();
+
+print("part 1 =",p1);
+print("part 2 =",p2);
diff --git a/2020/aoc2020-d03.py b/2020/aoc2020-d03.py
new file mode 100644
index 0000000..aa485e0
--- /dev/null
+++ b/2020/aoc2020-d03.py
@@ -0,0 +1,29 @@
+#advent of code 2020
+#day 03
+
+grid = dict();
+limY = 0;
+limX = 0;
+PuzzleInput = open("03.in","r");
+for y,line in enumerate(PuzzleInput):
+ for x, c in enumerate(line):
+ grid[(x,y)] = c;
+ limX = max(limX,x);
+ limY = max(limY,y);
+PuzzleInput.close();
+slopes = [(1,1),(3,1),(5,1),(7,1),(1,2)];
+p1 = 0;
+p2 = 1;
+for slope in slopes:
+ stepX, stepY = slope;
+ MyPosX = 0;
+ MyPosY = 0;
+ trees = 0;
+ while MyPosY < limY :
+ MyPosX += stepX;
+ MyPosY += stepY;
+ if grid[(MyPosX%limX),MyPosY] == "#": trees +=1;
+ p2 *= trees;
+ if slope == (3,1): p1 += trees;
+print("part 1 = ",p1);
+print("part 2 = ",p2);
diff --git a/2020/aoc2020-d04.py b/2020/aoc2020-d04.py
new file mode 100644
index 0000000..22f044d
--- /dev/null
+++ b/2020/aoc2020-d04.py
@@ -0,0 +1,42 @@
+#advent of code 2020
+#day 04
+import re
+
+PuzzleInput = open("04.in","r").read()
+passports = PuzzleInput.split("\n\n");
+p1 = 0;
+p2 = 0;
+documents = dict();
+required = ["byr","iyr","eyr","hgt","hcl","ecl","pid"]; #puzzle description
+
+def part2(doc):
+ valid2 = True;
+ valid2 *= len(doc["byr"]) == 4 and int(doc["byr"]) >= 1920 and int(doc["byr"]) <= 2002;
+ valid2 *= len(doc["iyr"]) == 4 and int(doc["iyr"]) >= 2010 and int(doc["iyr"]) <= 2020;
+ valid2 *= len(doc["eyr"]) == 4 and int(doc["eyr"]) >= 2020 and int(doc["eyr"]) <= 2030;
+ valid2 *= doc["hgt"][-2:] == "cm" or doc["hgt"][-2:] == "in";
+ if doc["hgt"][-2:] == "cm":
+ valid2 *= int(doc["hgt"][:-2]) >= 150 and int(doc["hgt"][:-2]) <= 193;
+ if doc["hgt"][-2:] == "in":
+ valid2 *= int(doc["hgt"][:-2]) >= 59 and int(doc["hgt"][:-2]) <= 76;
+ valid2 *= doc["hcl"][0] == "#";
+ valid2 *= len(re.findall("[a-f]|[0-9]",doc["hcl"])) == 6;
+ valid2 *= doc["ecl"] in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"];
+ valid2 *= len(doc["pid"]) == 9;
+ return valid2;
+
+for i,p in enumerate(passports):
+ p = p.replace("\n"," ")
+ documents[i] = dict();
+ for entry in p.split(" "):
+ if len(entry) == 0: continue;
+ k,v = entry.split(":");
+ documents[i][k] = v;
+ valid = True;
+ for req in required:
+ valid *= req in documents[i];
+ p1 += 1*valid;
+ if valid: p2 += 1*part2(documents[i]);
+
+print("part 1 =",p1);
+print("part 2 =",p2);
diff --git a/2020/aoc2020-d05.py b/2020/aoc2020-d05.py
new file mode 100644
index 0000000..ffc6ffb
--- /dev/null
+++ b/2020/aoc2020-d05.py
@@ -0,0 +1,33 @@
+#advent of code 2020
+#day 05
+#examples = ["BFFFBBFRRR","FFFBBBFRRR","BBFFBBFRLL"];
+def partitioner(instr, limLow, limHigh, splitLow, splitHigh):
+ diff = limHigh - limLow + 1;
+ if instr == "":
+ return limLow;
+ elif instr[0] == splitLow:
+ return partitioner(instr[1:], limLow, limHigh-diff//2, splitLow, splitHigh);
+ elif instr[0] == splitHigh:
+ return partitioner(instr[1:], limLow+diff//2, limHigh, splitLow, splitHigh);
+
+p1 = 0;
+AllSeats = [];
+PuzzleInput = open("05.in","r");
+
+for BoardingPass in PuzzleInput:
+ BP = BoardingPass.replace("\n","");
+ row = partitioner(BP[:-3],0,127,"F","B");
+ col = partitioner(BP[-3:],0,7,"L","R");
+ seatID = row*8 + col;
+ p1 = max(p1,seatID)
+ AllSeats.append(seatID)
+PuzzleInput.close();
+
+AllSeats = sorted(AllSeats);
+for n in range(1, len(AllSeats)):
+ if AllSeats[n] - AllSeats[n-1] != 1:
+ p2 = AllSeats[n-1] + 1;
+ break;
+
+print("part 1 = ",p1);
+print("part 2 = ",p2);
diff --git a/2020/aoc2020-d06.py b/2020/aoc2020-d06.py
new file mode 100644
index 0000000..8f0df5c
--- /dev/null
+++ b/2020/aoc2020-d06.py
@@ -0,0 +1,22 @@
+#advent of code 2020
+#day 06
+PuzzleInput = open("06.in","r").read();
+groups = PuzzleInput.split("\n\n");
+p1 = 0;
+p2 = 0;
+
+for group in groups:
+ anyone = group.replace("\n","");
+ p1 += len(set(list(anyone)));
+ everyone = group.split("\n");
+ answers = [];
+ for e in everyone:
+ if len(e) == 0: continue; #some minor adjustment bc parsing
+ answers.append(set(list(e)))
+ total = answers[0]; #answers of the first guy (1st line)
+ for a in answers[1:]:
+ total = total.intersection(a); #shrink the set to duplicates only
+ p2 += len(total);
+
+print("part 1 =",p1);
+print("part 2 =",p2);
diff --git a/2020/aoc2020-d07.py b/2020/aoc2020-d07.py
new file mode 100644
index 0000000..4be155f
--- /dev/null
+++ b/2020/aoc2020-d07.py
@@ -0,0 +1,48 @@
+#advent of code 2020
+#day 07
+#cool
+PuzzleInput = open("07.in","r");
+
+rules = {};
+target = "shinygold";
+queue = [];
+options = set();
+#parse, removing filler wording and splitting bag names to dictionary
+for line in PuzzleInput:
+ line = line.replace("\n","").replace(" bags","").replace(" bag","").replace("no other","1 no other")[:-1];
+ rk, rv = line.split(" contain "); #rule key, rule value
+ rv = rv.split(", ");
+ rk = rk.replace(" ","");
+ rules[rk] = dict();
+ for rval in rv:
+ rv1,rv2,rv3 = rval.split(" ");
+ rules[rk][rv2+rv3] = int(rv1);
+ if target in rules[rk]:
+ queue.append(rk);
+ options.add(rk);
+PuzzleInput.close();
+#part 1
+visited = [];
+while queue:
+ bag = queue.pop();
+ if bag in visited: continue;
+ visited.append(bag);
+ for rk in rules:
+ if bag in rules[rk]:
+ queue.append(rk);
+ options.add(rk);
+
+p1 = len(options);
+#part 2
+queue = [(1,target)];
+AllBags = dict();
+while queue:
+ total, bag = queue.pop();
+ for b in rules[bag]:
+ if b == "noother": continue;
+ AllBags[b] = AllBags.get(b,0) + total*rules[bag][b];
+ queue.append((total*rules[bag][b], b));
+
+p2 = sum([AllBags[bag] for bag in AllBags]);
+print("part 1 =",p1);
+print("part 2 =",p2);
diff --git a/2020/aoc2020-d08.py b/2020/aoc2020-d08.py
new file mode 100644
index 0000000..8965514
--- /dev/null
+++ b/2020/aoc2020-d08.py
@@ -0,0 +1,93 @@
+#advent of code 2020
+#day 08
+#a little bit bruteforce-ish,
+#for part 2 I mark instruction that are actually used by boot code
+#then I loop over the marked instructions and replace them 1 by 1 until
+#the infinite cycle is broken
+#also the input kept getting broken and needed to change the parsing
+#which isn't a hard bug, but an annoying one
+#ALSO during rewriting I figured out that I don't need to calculate
+#part 1 separately, it's already used during cycle detection
+#although this might just be a coincidence; honestly I'm not confident
+#in cycle detection puzzles
+
+BootCode = []
+PuzzleInput = open("08.in","r")
+for x in PuzzleInput:
+ if len(x) == 0: continue; #please ignore it, I'm bad at parsing
+ instr, val = x.split(" ");
+ BootCode.append(x.replace("\n",""));
+PuzzleInput.close();
+
+index = 0;
+accumulator = 0;
+visited = set();
+#the "Im sure it works" method for part 1
+while True:
+ instr, val = BootCode[index].split(" ");
+ #order += 1;
+ if index in visited: break;
+ visited.add(index);
+ if instr == "nop":
+ index += 1;
+ elif instr == "acc":
+ accumulator += int(val);
+ index += 1;
+ elif instr == "jmp":
+ index += int(val);
+
+print("part 1 =",accumulator);
+
+index = 0;
+accumulator = 0;
+accVals = dict();
+p1 = None;
+#the "it works for me but might be luck" method for part 1
+while index <= len(BootCode):
+ instr, val = BootCode[index].split(" ");
+ Current, Previous = accVals.get(index,(None,None));
+ if Previous and Current and Previous%accumulator == Previous%accumulator:
+ p1 = Current;
+ break;
+ accVals[index] = (accumulator, Current);
+ if instr == "nop":
+ index += 1;
+ elif instr == "acc":
+ accumulator += int(val);
+ index += 1;
+ elif instr == "jmp":
+ index += int(val);
+
+print("part 1 =",p1);
+
+p2 = None;
+for i in accVals:
+ if BootCode[i].split(" ")[0] == "acc": continue;
+ index = 0;
+ accumulator = 0;
+ accValsNested = dict();
+ NoCycle = True;
+ while index < len(BootCode):
+ instr, val = BootCode[index].split(" ");
+ Current, Previous = accValsNested.get(index,(None,None));
+ if Previous and Current and Previous%accumulator == Previous%accumulator:
+ NoCycle = False;
+ break;
+ accValsNested[index] = (accumulator, Current);
+ if index == i: #swap instructions
+ if instr == "nop":
+ instr = "jmp";
+ elif instr == "jmp":
+ instr = "nop";
+ if instr == "nop":
+ index += 1;
+ elif instr == "acc":
+ accumulator += int(val);
+ index += 1;
+ elif instr == "jmp":
+ index += int(val);
+ if NoCycle:
+ p2 = accumulator;
+ break;
+
+print("part 2 =", p2);
diff --git a/2020/aoc2020-d09.py b/2020/aoc2020-d09.py
new file mode 100644
index 0000000..26c1c61
--- /dev/null
+++ b/2020/aoc2020-d09.py
@@ -0,0 +1,55 @@
+#advent of code 2020
+#day 09
+#genuinely surprised the simple solution worked
+#shamelessly googled the code for combinations,
+#didn't feel like implementing it
+#if i reversed the "visited" list the runtime could be faster but w/e
+
+def PossibleCombs(n,k):
+ combinations = [];
+ if k==1: return n;
+ for i in range(len(n)):
+ head = n[i:i+1]
+ tail = PossibleCombs(n[i+1:],k-1);
+ for j in range(len(tail)):
+ if type(tail[j]) == int:
+ comb = head + [tail[j]]
+ else:
+ comb = head + tail[j];
+ combinations.append(comb);
+ return combinations;
+
+p1 = None;
+limit = 25;
+numbers = [];
+PuzzleInput = open("09.in","r");
+for line in PuzzleInput: numbers.append(int(line));
+PuzzleInput.close();
+previous = numbers[:limit];
+counter = limit -1;
+
+for n in numbers[limit:]:
+ counter += 1;
+ found = False;
+ for combo in PossibleCombs(previous,2):
+ if n == sum(combo):
+ previous = previous[1:] + [n];
+ found = True;
+ break;
+ if not found:
+ p1 = n;
+ break;
+
+visited = numbers[:counter];
+for i,n in enumerate(visited):
+ subsum = 0 + n;
+ subcounter = 0 + i;
+ while subsum < p1:
+ subcounter += 1;
+ subsum += visited[subcounter];
+ if subsum == p1:
+ p2 = min(visited[i:subcounter]) + max(visited[i:subcounter]) ;
+ break;
+
+print("part 1 =",p1);
+print("part 2 =",p2);
diff --git a/2020/aoc2020-d10.py b/2020/aoc2020-d10.py
new file mode 100644
index 0000000..a86b976
--- /dev/null
+++ b/2020/aoc2020-d10.py
@@ -0,0 +1,39 @@
+#advent of code 2020
+#day 10
+#very similar (if not identical) to towels puzzle, 2024-d19
+#memorize previous paths and just sum up the valid paths for each adapter
+#although this one i think is easier due to no duplicates
+#and working on numbers instead of characters
+bag = [];
+PuzzleInput = open("10.in","r");
+for num in PuzzleInput: bag.append(int(num));
+PuzzleInput.close();
+#first and last items are from puzzle description
+bag = [0] + [x for x in sorted(bag)] + [max(bag) +3];
+connections = dict();
+connections[1] = 0;
+connections[2] = 0;
+connections[3] = 0;
+#since there are no duplicates and all adapters must be connected
+#we can just check against the previous value for part 1;
+for index in range(1,len(bag)):
+ adapter1 = bag[index];
+ adapter2 = bag[index-1];
+ diff = adapter1 - adapter2;
+ connections[diff] += 1;
+
+p1 = connections[1] * connections[3];
+
+p2 = 0;
+options = dict();
+options[0] = 1;
+for index in range(1,len(bag)):
+ previous = bag[:index];
+ possible = [x for x in previous if bag[index] - x <=3];
+ options[bag[index]] = 0;
+ for poss in possible:
+ options[bag[index]] += options[poss];
+
+p2 = options[max(bag)];
+print("part 1 =",p1);
+print("part 2 =",p2);