summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbthink <bthink@fake.com>2025-12-12 12:42:43 +0100
committerbthink <bthink@fake.com>2025-12-12 12:42:43 +0100
commitde308443f4ed4e12cd18578af09b93d7d01e2a84 (patch)
treee8977d445fe6a86b45dfc8bec8aa46b1fddde76c
parented395fe7a7fd68f6db4ea94de8fdcdcb0fac5179 (diff)
final week of 2025HEADmasterbthink
-rw-r--r--2025/aoc2025-d08.py69
-rw-r--r--2025/aoc2025-d09.py92
-rw-r--r--2025/aoc2025-d10.py76
-rw-r--r--2025/aoc2025-d11.py35
-rw-r--r--2025/aoc2025-d12.py39
5 files changed, 311 insertions, 0 deletions
diff --git a/2025/aoc2025-d08.py b/2025/aoc2025-d08.py
new file mode 100644
index 0000000..2e053eb
--- /dev/null
+++ b/2025/aoc2025-d08.py
@@ -0,0 +1,69 @@
+#advent of code 2025
+#day 08
+
+def getDistance(j1,j2):
+ jx1,jy1,jz1=j1;
+ jx2,jy2,jz2=j2;
+ euclid=(jx2-jx1)*(jx2-jx1) + (jy2-jy1)*(jy2-jy1) + (jz2-jz1)*(jz2-jz1);
+ #no real need to take square root since if a^2 > b^2 then a > b
+ #no negatives since it's distance
+ return euclid;
+#parsing
+boxes=[];
+limit=1000; #10 for example
+PuzzleInput=open("08.in","r");
+for line in PuzzleInput:
+ boxes.append(tuple([int(p) for p in line.split(",")]));
+PuzzleInput.close();
+
+numberOfBoxes=len(boxes);
+distances=set();
+for bi1,b1 in enumerate(boxes):
+ for bi2,b2 in enumerate(boxes):
+ if bi2==bi1:continue;
+ d1=getDistance(b1,b2);
+ distances.add((d1,tuple(sorted((b1,b2))) ) );
+distances=sorted(distances,key=lambda m: m[0]);
+
+circuits=dict();
+for di in range(len(distances)):
+ d,boxtuple=distances[di];
+ box1,box2=boxtuple;
+ if box1 not in circuits and box2 not in circuits:
+ circuits[box1]=set([box1,box2]); #first box contains the circuit
+ circuits[box2]=box1; #second box links to first one
+ elif box1 in circuits and box2 not in circuits:
+ b3=box1; #find the box which has the circuit set assigned in dictionary
+ while type(circuits[b3])!=set:
+ b3=circuits[b3];
+ circuits[b3].add(box2);
+ circuits[box2]=b3;
+ elif box2 in circuits and box1 not in circuits:
+ b4=box2;
+ while type(circuits[b4])!=set:
+ b4=circuits[b4];
+ circuits[b4].add(box1);
+ circuits[box1]=b4;
+ elif box2 in circuits and box1 in circuits:
+ b3=box1;
+ while type(circuits[b3])!=set:
+ b3=circuits[b3];
+ b4=box2;
+ while type(circuits[b4])!=set:
+ b4=circuits[b4];
+ if b3==b4: continue;
+ circuits[b3].update(circuits[b4]);
+ circuits[b4]=b3;
+
+ clustering=sorted([len(circuits[cluster]) for cluster in circuits if type(circuits[cluster])==set],reverse=True);
+ if clustering[0]==numberOfBoxes:
+ part2=box1[0]*box2[0];
+ break;
+
+ if di==limit:
+ part1=1;
+ for i in range(3):
+ part1*=clustering[i];
+
+print("part 1 =",part1, part1==103488);
+print("part 2 =",part2, part2==8759985540);
diff --git a/2025/aoc2025-d09.py b/2025/aoc2025-d09.py
new file mode 100644
index 0000000..df7be78
--- /dev/null
+++ b/2025/aoc2025-d09.py
@@ -0,0 +1,92 @@
+#advent of code 2025
+#day 09
+#bit slow
+#tried adding comments but will probably forget how it works anyway
+
+tiles=[];
+Ymax=0;
+Xmax=0;
+Ymin=10000000;
+Xmin=10000000;
+PuzzleInput=open("09.in","r");
+for l in PuzzleInput:
+ t=tuple([int(v) for v in l.split(",")]);
+ tiles.append(t);
+ Xmax=max(Xmax,t[0]);
+ Ymax=max(Ymax,t[1]);
+ Xmin=min(Xmin,t[0]);
+ Ymin=min(Ymin,t[1]);
+PuzzleInput.close();
+
+part1=0;
+green=set();
+for ci1,corner1 in enumerate(tiles):
+ x1,y1=corner1;
+ for ci2,corner2 in enumerate(tiles):
+ if ci1==ci2: continue;
+ x2,y2=corner2;
+ area=(abs(x1-x2)+1)*(abs(y1-y2)+1);
+ part1=max(part1,area);
+
+part2=0;
+#create the perimiter of the figure ("green" set)
+#check how big is a distance between each tile
+#tiles are ordered
+delta=[(1,0),(0,1)]
+distancedTiles=[];
+test=0;
+maxdist=0;
+for t in range(len(tiles)):
+ tile1=tiles[t];
+ tile2=tiles[(t+1)%len(tiles)];
+ for i in range(2):
+ if tile1[i]==tile2[i]: continue;
+ dx,dy=delta[i];
+ steps=tile2[i]-tile1[i];
+ dd=1*(steps>0) -1*(steps<0);
+ for step in range(abs(steps)):
+ green.add((tile1[0]+dx*dd*step,tile1[1]+dy*dd*step));
+ distancedTiles.append((abs(steps),tile1,tile2,i));
+ maxdist=max(maxdist,abs(steps));
+#sort the distances from longest to shortest
+distancedTiles=sorted(distancedTiles,key=lambda m: m[0],reverse=True);
+#check if the candidate "dt" isn't an order of 10 lower compared to biggest distance
+#the biggest area has to be along the longest edge
+candidates=[dt for dt in distancedTiles if maxdist//dt[0]<10];
+for can_i in range(len(candidates)):
+ candidate=candidates[can_i];
+ d,can1,can2,can_orient=candidate;
+ orient_1=candidates[(can_i)%len(candidates)][1][(can_orient+1)%2];
+ orient_2=candidates[(can_i+1)%len(candidates)][1][(can_orient+1)%2];
+
+ if orient_1 > orient_2:
+ lim_1=orient_1;
+ lim_2=Ymax+1;
+ else:
+ lim_1=0;
+ lim_2=orient_1+1;
+
+ can=sorted([can1,can2],key=lambda m:m[0])[1]
+ otherCandidates=[ocand for ocand in tiles if ocand[(can_orient+1)%2] in range(lim_1,lim_2)];
+ for ocand in otherCandidates:
+ #check if the X edge isn't in the way of perimiter (the longest edge doesn't count)
+ checkX=True;
+ for s in range(1+min(ocand[0],can[0]),max(ocand[0],can[0]) -1):
+ if can[0]==s: continue;
+ if (s,ocand[1]) in green:
+ checkX=False;
+ break;
+ if not checkX: continue;
+ #check if the Y edge isn't in the way of perimiter
+ checkY=True;
+ for s in range(1+min(ocand[1],can[1]),max(ocand[1],can[1]) -1):
+ if (can[0],s) in green:
+ checkY=False;
+ break;
+ if not checkY: continue;
+
+ area2=(abs(can[0]-ocand[0])+1)*(abs(can[1]-ocand[1])+1);
+ part2=max(part2,area2);
+
+print("part 1 =",part1);
+print("part 2 =",part2);
diff --git a/2025/aoc2025-d10.py b/2025/aoc2025-d10.py
new file mode 100644
index 0000000..17cb090
--- /dev/null
+++ b/2025/aoc2025-d10.py
@@ -0,0 +1,76 @@
+#advent of code 2025
+#day 10
+#can probably rewrite it from scratch instead of using z3
+#will try later
+#part 1 is way too slow as well
+
+from z3 import *
+import heapq
+
+machineInstructions=[];
+PuzzleInput=open("10.in","r");
+for l in PuzzleInput:
+ l=l.strip();
+ diagram, residue=l.split("] ");
+ diagram=list([1*(light=="#") for light in diagram.replace("[","")])
+ buttons, joltage = residue.split(" {");
+ joltage=list([int(jolt) for jolt in joltage.replace("}","").split(",")]);
+ buttons=[tuple([int(but) for but in button.replace(")","").replace("(","").split(",")]) for button in buttons.split(" ")];
+ machineInstructions.append((diagram, buttons, joltage));
+PuzzleInput.close();
+
+#part 1
+def findSequence(machinstr):
+ target,options,power=machinstr; #power unused
+ state=[0 for t in target];
+ visited=list();
+ queue=[];
+ heapq.heappush(queue,(0,state,[0 for b in range(len(options))]));
+ while queue:
+ presses,currentState,prevButtons=heapq.heappop(queue);
+ if currentState==target:
+ return presses;
+ if prevButtons in visited:
+ continue;
+ visited.append(prevButtons);
+
+ for o in range(len(options)):
+ newstate=[cs for cs in currentState];
+ for s in options[o]:
+ newstate[s]=(newstate[s]+1)%2;
+ newbuttons=[prevButtons[b]+1*(b==o) for b in range(len(prevButtons))];
+ heapq.heappush(queue,(presses+1,newstate,newbuttons));
+ return 999999;
+
+def adjustPower(machinstr):
+ lights,options,power=machinstr; #lights unused
+ buttons=[[1*(b in but) for b in range(len(power))] for but in options];
+ solver=z3.Optimize();
+ xVector=[z3.Int(f'x{x}') for x in range(len(buttons))];
+ powerVector=[z3.Int(f'p{p}') for p in range(len(power))];
+
+ for x in range(len(buttons)):
+ solver.add(z3.Int(f'x{x}')>=0);
+
+ for p in range(len(powerVector)):
+ solver.add(powerVector[p]==power[p]);
+
+ for p in range(len(power)):
+ solver.add(powerVector[p]==z3.Sum([xVector[x] for x in range(len(buttons)) if buttons[x][p]==1]));
+
+ solver.minimize(z3.Sum(xVector));
+ solver.check();
+ model=solver.model();
+ presses=[model[mult].as_long() for mult in xVector];
+ score=sum(presses);
+ return score
+
+
+part1=0;
+part2=0;
+
+for mi,instr in enumerate(machineInstructions):
+ part1+=findSequence(instr);
+ part2+=adjustPower(instr);
+print("part 1",part1);
+print("part 2",part2);
diff --git a/2025/aoc2025-d11.py b/2025/aoc2025-d11.py
new file mode 100644
index 0000000..86af8aa
--- /dev/null
+++ b/2025/aoc2025-d11.py
@@ -0,0 +1,35 @@
+#advent of code 2025
+#day 11
+#more reading for later, maybe there's a different algo than dfs/bfs
+# https://en.wikipedia.org/wiki/Directed_acyclic_graph
+#no idea why my format doesn't work
+#below is format which was shamelessly stolen from someone else
+#don't sue me
+#will rewrite it later as a product
+#possible paths svr-fft; possible paths fft-dac; possible paths dac-out
+
+from functools import cache
+
+connections=dict();
+PuzzleInput=open("11.in","r");
+for l in PuzzleInput:
+ vertex,nodes=l.strip().split(": ");
+ if vertex not in connections: connections[vertex]=set();
+ connections[vertex].update(nodes.split())
+
+@cache
+def findpaths(pos,fft,dac):
+ if pos=="out":
+ return 1*fft*dac;
+ score=0;
+ fft_=fft or pos=="fft";
+ dac_=dac or pos=="dac";
+ for con in connections[pos]:
+ score+=findpaths(con,fft_,dac_);
+ return score;
+
+part1=findpaths("you",True,True);
+part2=findpaths("svr",False,False);
+
+print("part 1 =",part1);
+print("part 2 =",part2);
diff --git a/2025/aoc2025-d12.py b/2025/aoc2025-d12.py
new file mode 100644
index 0000000..725144c
--- /dev/null
+++ b/2025/aoc2025-d12.py
@@ -0,0 +1,39 @@
+#advent of code 2025
+#day 12
+
+part1=0;
+gifts=[];
+trees=[];
+ID=None;
+PuzzleInput=open("12.in","r");
+for line in PuzzleInput:
+ line=line.strip();
+ if "x" in line:
+ dimensions, quantities=line.split(": ");
+ dimensions=tuple([int(d) for d in dimensions.split("x")]);
+ quantities=[int(q) for q in quantities.split(" ")];
+ trees.append((dimensions,quantities));
+ elif ID==None:
+ ID=int(line.replace(":",""));
+ gifts.append([]);
+ elif len(line)==0:
+ ID=None;
+ else:
+ gifts[ID].append(list(line));
+
+def validateTree(tree,presents):
+ grid,reqs=tree;
+ space=grid[0]*grid[1];
+ minX,minY=0,0;
+ for ID,r in enumerate(reqs):
+ pr=presents[ID];
+ dimY=max([pr[j].count("#") for j in range(len(pr))]);
+ dimX=max( [sum([pr[j][i].count("#") for j in range(len(pr))]) for i in range(len(pr[0]))] );
+ minX+=r*dimX;
+ minY+=r*dimY;
+ space-=r*dimX*dimY;
+ return space>0;
+
+for t in trees:
+ part1+=1*validateTree(t,gifts);
+print("part 1 =",part1);