summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorblenovo <bk@gmail.com>2025-08-06 00:51:06 +0200
committerblenovo <bk@gmail.com>2025-08-06 00:51:06 +0200
commit0a441ce2306ae9edefb009fbc0596f4d511cdc7f (patch)
tree11d5aca4383bbce8a35acb912698f473b8180215
parent12f551dbfef138880b29ba6abe4576714ae942cb (diff)
summertime warmup session - finish
-rw-r--r--2020/aoc2020-d21.py41
-rw-r--r--2020/aoc2020-d22.py74
-rw-r--r--2020/aoc2020-d23.py58
-rw-r--r--2020/aoc2020-d24.py85
-rw-r--r--2020/aoc2020-d25.py29
5 files changed, 287 insertions, 0 deletions
diff --git a/2020/aoc2020-d21.py b/2020/aoc2020-d21.py
new file mode 100644
index 0000000..f6edea8
--- /dev/null
+++ b/2020/aoc2020-d21.py
@@ -0,0 +1,41 @@
+#advent of code 2020
+#day 21
+#part 2 very similar to ticket problem from the same year
+
+ingredients = [];
+AllergyDict = dict();
+PossibleAllergens = set();
+AssignedAllergens = dict();
+
+PuzzleInput = open("21.in","r");
+for line in PuzzleInput:
+ line = line.replace("\n","");
+ FoodIngr, FoodAllr = line[:-1].split(" (contains ");
+ FoodIngr = FoodIngr.split(" ");
+ FoodAllr = FoodAllr.split(", ");
+ ingredients.extend(FoodIngr);
+ for a in FoodAllr:
+ if a in AllergyDict:
+ AllergyDict[a].intersection_update(set(FoodIngr));
+ else:
+ AllergyDict[a] = set(FoodIngr);
+PuzzleInput.close();
+
+for al in AllergyDict:
+ print(al, AllergyDict[al]);
+ PossibleAllergens.update(AllergyDict[al]);
+
+p1 = len([i for i in ingredients if i not in PossibleAllergens]);
+print("part 1 =",p1);
+
+while len(AssignedAllergens) != len(AllergyDict):
+ #print(len(AssignedAllergens),"/", len(AllergyDict)); #in case it takes long
+ for al in AllergyDict:
+ if len(AllergyDict[al]) == 1:
+ found = AllergyDict[al].pop();
+ AssignedAllergens[al] = found;
+ else:
+ AllergyDict[al].difference_update( AssignedAllergens.values() );
+
+p2 = ",".join([AssignedAllergens[allergen] for allergen in sorted(AssignedAllergens.keys())]);
+print("part 2 =",p2);
diff --git a/2020/aoc2020-d22.py b/2020/aoc2020-d22.py
new file mode 100644
index 0000000..01b9a4c
--- /dev/null
+++ b/2020/aoc2020-d22.py
@@ -0,0 +1,74 @@
+#advent of code 2020
+#day 22
+#some problems with copying, modifying, accessing data between functions
+#had a bit of workarounds
+#Im too lazy to reduce the amount of code
+#by including part1 and part2 in a single function
+
+def NormalCombat(player1, player2):
+ decks = dict();
+ decks[0] = player1.copy();
+ decks[1] = player2.copy();
+ while len(decks[0]) > 0 and len(decks[1]) > 0 :
+ card0 = decks[0].pop(0);
+ card1 = decks[1].pop(0);
+ if card0 > card1:
+ decks[0].append(card0);
+ decks[0].append(card1);
+ elif card0 < card1:
+ decks[1].append(card1);
+ decks[1].append(card0);
+ score = 0;
+ for deck in decks:
+ if len(decks[deck]) == 0: continue;
+ for c, card in enumerate(decks[deck]):
+ score += (len(decks[deck])-c)*card
+ break;
+ return score;
+
+def RecursiveCombat(player1, player2):
+ decks = dict();
+ decks[0] = player1.copy();
+ decks[1] = player2.copy();
+ previoushands = dict();
+ previoushands[0] = [];
+ previoushands[1] = [];
+ while len(decks[0]) > 0 and len(decks[1]) > 0 :
+ if tuple(decks[0]) in previoushands[0] and tuple(decks[1]) in previoushands[1]:
+ return 0, None;
+ previoushands[0].append(tuple(decks[0]));
+ previoushands[1].append(tuple(decks[1]));
+ card0 = decks[0].pop(0);
+ card1 = decks[1].pop(0);
+ if card0 <= len(decks[0]) and card1 <= len(decks[1]):
+ winner, winscore = RecursiveCombat(decks[0][:card0],decks[1][:card1]);
+ elif card0 > card1:
+ winner = 0;
+ elif card0 < card1:
+ winner = 1;
+ playedcards = [card0,card1];
+ decks[winner].append(playedcards[winner]);
+ decks[winner].append(playedcards[(winner+1)%2]);
+ score = 0;
+ for deck in decks:
+ #print(decks[deck]);
+ if len(decks[deck]) == 0: continue;
+ for c, card in enumerate(decks[deck]):
+ score += (len(decks[deck])-c)*card
+ winplayer = 0 + deck;
+ break;
+ return winplayer, score;
+
+PuzzleInput = open("22.in","r").read();
+playerdata1, playerdata2 = PuzzleInput.split("\n\n");
+playerdecks = dict();
+for pi, playerdata in enumerate( [playerdata1,playerdata2] ):
+ playerdecks[pi] = [int(val) for val in playerdata.split("\n")[1:] if val != ""];
+
+p1 = NormalCombat(playerdecks[0],playerdecks[1]);
+print("part 1 =",p1);
+_, p2 = RecursiveCombat(playerdecks[0],playerdecks[1]);
+print("part 2 =",p2);
+print('''part 1 = 34664
+part 2 = 32018
+''');
diff --git a/2020/aoc2020-d23.py b/2020/aoc2020-d23.py
new file mode 100644
index 0000000..b0bb6c0
--- /dev/null
+++ b/2020/aoc2020-d23.py
@@ -0,0 +1,58 @@
+#advent of code 2020
+#day 23
+#kinda cheated, I used another guy's solution for debugging
+# https://0xdf.gitlab.io/adventofcode2020/23 (cool source btw)
+#turns out my dictionary was getting one value from input replaced
+#which caused "cutting off" most of the other numbers
+#also tried filling out the dictionary with all numbers
+#but I was getting confused by different indexation
+#puzzle uses (0,1mil] instead of "standard" [0,1mil)
+#also minor mistakes in substitution ordering
+PuzzleInput = open("23.in","r").read().replace("\n","");
+cups = [int(v) for v in PuzzleInput];
+
+def cupgame(cuplabels, lim, cuplim):
+ cupdict = dict();
+ for c_i in range(len(cuplabels) -1):
+ cupdict[cuplabels[c_i]] = cuplabels[c_i+1];
+ if cuplim == len(cuplabels):
+ cupdict[cuplabels[-1]] = cuplabels[0];
+ else:
+ cupdict[cuplabels[-1]] = 10;
+ for c_i in range(len(cuplabels)+1,cuplim):
+ cupdict[c_i] = c_i + 1;
+ cupdict[ cuplim ] = cuplabels[0];
+
+ c0 = 0 + cuplabels[0];
+ for step in range(lim):
+ if step%1000000 == 0: print(step//1000000,"/",lim//1000000);
+ c1 = cupdict[c0] #,(c0+1)%(cuplim+1) +1);
+ c2 = cupdict[c1] #,(c1+1)%(cuplim+1) +1);
+ c3 = cupdict[c2] #,(c2+1)%(cuplim+1) +1);
+ cupdict[c0] = cupdict[c3] #,(c3+1)%(cuplim+1) +1);
+ d0 = c0 - 1;
+ if d0 == 0: d0 = cuplim;
+ while True:
+ if d0 not in [c1,c2,c3]: break;
+ d0 -= 1;
+ if d0 == 0: d0 = cuplim;
+ cupdict[c3] = cupdict[d0];
+ cupdict[d0] = c1;
+ c0 = cupdict[c0];
+
+ if cuplim == len(cuplabels):
+ solution = "";
+ NextVal = 1;
+ for s in range(8):
+ NextVal = cupdict[NextVal];
+ solution += str(NextVal);
+ else:
+ solution = cupdict[1] * cupdict[cupdict[1]];
+
+ return solution;
+
+p1 = cupgame(cups,100, len(cups));
+p2 = cupgame(cups,10000000, 1000000);
+print("part 1 =",p1);
+print("part 2 =",p2);
+
diff --git a/2020/aoc2020-d24.py b/2020/aoc2020-d24.py
new file mode 100644
index 0000000..c886be1
--- /dev/null
+++ b/2020/aoc2020-d24.py
@@ -0,0 +1,85 @@
+#advent of code 2020
+#day 24
+# https://www.redblobgames.com/grids/hexagons/
+# nested ifs in CheckAdjacent function aren't really slower than
+# making it a function, so i'm leaving it bc its more readable that way
+
+def CheckAdjacent(point, blackset):
+ black = 0;
+ py,px,pz = point;
+ for dkey in directions:
+ dx,dy,dz = directions[dkey];
+ p = (py+dy,px+dx, pz+dz);
+ if p in blackset:
+ black += 1;
+
+ if point in blackset:
+ if black == 0 or black > 2:
+ return False;
+ else:
+ return True;
+ else:
+ if black == 2:
+ return True;
+ else:
+ return False;
+
+tilesteps = [];
+
+PuzzleInput = open("24.in","r")
+for line in PuzzleInput:
+ line = line.replace("\n","");
+ instructions = [];
+ i = 0;
+ while i < len(line):
+ if line[i] in ["n","s"]:
+ instructions.append(line[i:i+2]);
+ i += 2;
+ else:
+ instructions.append(line[i]);
+ i += 1;
+ tilesteps.append(instructions);
+PuzzleInput.close();
+
+directions = dict();
+directions["e"] = (1,0,-1);
+directions["w"] = (-1,0,1);
+directions["ne"] = (1,-1,0);
+directions["nw"] = (0,-1,1);
+directions["sw"] = (-1,1,0);
+directions["se"] = (0,1,-1);
+
+grid = dict();
+# 0 - white
+# 1 - black
+
+for tilestep in tilesteps:
+ p = (0,0,0);
+ for step in tilestep:
+ py,px,pz = p;
+ dy,dx,dz = directions[step];
+ p = (py+dy,px+dx, pz+dz);
+ grid[p] = ( grid.get(p,0) + 1)%2;
+
+blacks = set();
+part1 = 0;
+for g in grid:
+ if grid[g] == 1:
+ part1 += 1;
+ blacks.add(g);
+
+print("part 1 =", part1);
+
+days = 100;
+for day in range(days):
+ NewBlacks = set();
+ for b in blacks:
+ if CheckAdjacent(b,blacks): NewBlacks.add(b);
+ for coord in directions.values():
+ n = (b[0] + coord[0],b[1] + coord[1],b[2] + coord[2]);
+ if CheckAdjacent(n,blacks): NewBlacks.add(n);
+ blacks = set();
+ blacks.update(NewBlacks);
+
+part2 = len(blacks);
+print("part 2 =", part2);
diff --git a/2020/aoc2020-d25.py b/2020/aoc2020-d25.py
new file mode 100644
index 0000000..28d1afe
--- /dev/null
+++ b/2020/aoc2020-d25.py
@@ -0,0 +1,29 @@
+#advent of code 2020
+#day 25
+#I made a mistake by thinking that subject number is an unknow
+#while in reality it actually is =7 as in puzzle description
+
+def FindNumbers(pubkey):
+ S = 7;
+ L = 0;
+ v = 1;
+ while True:
+ L += 1;
+ v *= S;
+ v = v%20201227;
+ if v == pubkey:
+ return L; #gives loop number
+
+PuzzleInput = open("25.in","r").read().split("\n");
+cardkey = int(PuzzleInput[0]);
+doorkey = int(PuzzleInput[1]);
+#encryption key is the same
+#whether we use loop of card + subject of door
+#or loop of door + subject of card
+encryption = 1;
+for l in range(FindNumbers(cardkey)):
+ encryption *= doorkey;
+ encryption = encryption%20201227;
+
+part1 = encryption;
+print("part 1 =", part1);