├── .gitignore ├── populate.sh ├── aoc-2023 ├── Day-06 │ ├── Python │ │ └── main.py │ ├── Ruby │ │ └── main.rb │ └── Java │ │ └── Main.java ├── run_basilisk.py ├── Day-04 │ └── Python │ │ └── main.py ├── Day-07 │ └── Python │ │ └── main.py ├── Day-09 │ └── Python │ │ └── main.py ├── Day-13 │ └── Python │ │ └── main.py ├── Day-02 │ └── Python │ │ └── main.py ├── Day-08 │ └── Python │ │ └── main.py ├── Day-01 │ └── Python │ │ └── main.py ├── Day-18 │ └── Python │ │ └── main.py ├── Day-15 │ └── Python │ │ └── main.py ├── Day-21 │ └── Python │ │ └── main.py ├── Day-11 │ └── Python │ │ └── main.py ├── Day-12 │ └── Python │ │ └── main.py ├── Day-14 │ └── Python │ │ └── main.py ├── Day-03 │ └── Python │ │ └── main.py ├── Day-16 │ └── Python │ │ └── main.py ├── Day-19 │ └── Python │ │ └── main.py ├── Day-17 │ └── Python │ │ └── main.py ├── Day-05 │ └── Python │ │ └── main.py ├── Day-22 │ └── Python │ │ └── main.py ├── Day-10 │ └── Python │ │ └── main.py ├── Day-20 │ └── Python │ │ └── main.py ├── Day-23 │ └── Python │ │ └── main.py ├── Day-25 │ └── Python │ │ └── main.py ├── Day-24 │ └── Python │ │ └── main.py └── basilisk.py ├── aoc-2024 ├── Day-03 │ └── Python │ │ └── main.py ├── Day-01 │ └── Python │ │ └── main.py ├── Day-02 │ └── Python │ │ └── main.py ├── Day-18 │ └── Python │ │ └── main.py ├── Day-13 │ └── Python │ │ └── main.py ├── Day-22 │ └── Python │ │ └── main.py ├── run_basilisk.py ├── Day-11 │ └── Python │ │ └── main.py ├── Day-08 │ └── Python │ │ └── main.py ├── Day-04 │ └── Python │ │ └── main.py ├── Day-19 │ └── Python │ │ └── main.py ├── Day-05 │ └── Python │ │ └── main.py ├── Day-07 │ └── Python │ │ └── main.py ├── Day-09 │ └── Python │ │ └── main.py ├── Day-14 │ └── Python │ │ └── main.py ├── Day-12 │ └── Python │ │ └── main.py ├── Day-23 │ └── Python │ │ └── main.py ├── Day-25 │ └── Python │ │ └── main.py ├── Day-06 │ └── Python │ │ └── main.py ├── Day-10 │ └── Python │ │ └── main.py ├── Day-16 │ └── Python │ │ └── main.py ├── Day-17 │ └── Python │ │ └── main.py ├── Day-20 │ └── Python │ │ └── main.py ├── Day-15 │ └── Python │ │ └── main.py ├── Day-24 │ └── Python │ │ └── main.py ├── Day-21 │ └── Python │ │ └── main.py └── basilisk.py ├── aoc-2025 ├── Day-01 │ └── Python │ │ └── main.py ├── Day-02 │ └── Python │ │ └── main.py ├── Day-03 │ └── Python │ │ └── main.py ├── Day-06 │ └── Python │ │ └── main.py ├── Day-12 │ └── Python │ │ └── main.py ├── run_basilisk.py ├── Day-05 │ └── Python │ │ └── main.py ├── Day-04 │ └── Python │ │ └── main.py ├── Day-11 │ └── Python │ │ └── main.py ├── Day-07 │ └── Python │ │ └── main.py ├── Day-08 │ └── Python │ │ └── main.py ├── Day-09 │ └── Python │ │ └── main.py ├── Day-10 │ └── Python │ │ └── main.py └── basilisk.py ├── speed.sh ├── .gitmodules ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.png 2 | *.pdf 3 | *.class 4 | *.in 5 | *.svg 6 | main 7 | mainc 8 | visualize.py 9 | automate.py 10 | __pycache__/ -------------------------------------------------------------------------------- /populate.sh: -------------------------------------------------------------------------------- 1 | export Y=2025 2 | cd /workspaces/advent-of-code/aoc-$Y 3 | for i in $(seq -f '%02g' 1 12) 4 | do mkdir -p Day-$i && touch Day-$i/$i.in && mkdir -p Day-$i/Python && touch Day-$i/Python/main.py 5 | done -------------------------------------------------------------------------------- /aoc-2023/Day-06/Python/main.py: -------------------------------------------------------------------------------- 1 | import math 2 | l = [input().split()[1:] for _ in '..'] 3 | g = lambda a,b: a-1-2*int((a-(a*a-4*b)**0.5)/2) 4 | print('Part 1:', math.prod(g(*map(int,i)) for i in zip(*l))) 5 | print('Part 2:', g(*map(int,map(''.join, l)))) -------------------------------------------------------------------------------- /aoc-2024/Day-03/Python/main.py: -------------------------------------------------------------------------------- 1 | import re 2 | t = ('do()'+open(0).read()).split("don't()") 3 | f = lambda p: sum(int(a)*int(b) for r in t for a,b in re.findall('mul\((\d+),(\d+)\)', r[r.find('do()')*p:])) 4 | print('Part 1:', f(0)) 5 | print('Part 2:', f(1)) -------------------------------------------------------------------------------- /aoc-2024/Day-01/Python/main.py: -------------------------------------------------------------------------------- 1 | A, B = [], [] 2 | for x in open(0): 3 | a, b = map(int, x.split()) 4 | A.append(a), B.append(b) 5 | A.sort(), B.sort() 6 | print('Part 1:', sum(abs(x-y) for x,y in zip(A, B))) 7 | print('Part 2:', sum(x*B.count(x) for x in A)) -------------------------------------------------------------------------------- /aoc-2025/Day-01/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | x = 50; p1 = p2 = 0 3 | for i in sys.stdin: 4 | d, v = -1 if i[0] == 'L' else 1, int(i[1:]) 5 | p2 += v//100; v %= 100 6 | for _ in '.'*v: x = (x+d)%100; p2 += x == 0 7 | p1 += x == 0 8 | print('Part 1:', p1) 9 | print('Part 2:', p2) -------------------------------------------------------------------------------- /speed.sh: -------------------------------------------------------------------------------- 1 | export Y=2024 2 | export TIMEFORMAT='Time: %3R seconds' 3 | cd ~/advent-of-code/aoc-$Y 4 | for i in $(seq -f '%02g' 1 25) 5 | do aocd $Y $i > Day-$i/$i.in 6 | done 7 | for i in $(seq -f '%02g' 1 25) 8 | do echo "Day $i:" && time python Day-$i/Python/main.py < Day-$i/$i.in && echo 9 | done -------------------------------------------------------------------------------- /aoc-2025/Day-02/Python/main.py: -------------------------------------------------------------------------------- 1 | p1 = p2 = 0 2 | for s in input().split(','): 3 | a, b = map(int, s.split('-')) 4 | for i in range(a, b+1): 5 | k = len(s:=str(i)) 6 | for l in range(2, k+1): 7 | if s[:k//l]*l == s: p1 += i*(l==2); p2 += i; break 8 | print('Part 1:', p1) 9 | print('Part 2:', p2) -------------------------------------------------------------------------------- /aoc-2023/run_basilisk.py: -------------------------------------------------------------------------------- 1 | import os, time 2 | with open('basilisk.py') as f: lines = f.readlines() 3 | for day in range(1, 26): 4 | print(f'Day {day:02d}') 5 | t = time.time() 6 | os.system(f'''python3.8 -c "{lines[2*day-1]}" < Day-{day:02d}/{day:02d}.in''') 7 | print(f'Time: {round(time.time()-t, 3)} seconds\n') -------------------------------------------------------------------------------- /aoc-2024/Day-02/Python/main.py: -------------------------------------------------------------------------------- 1 | a = b = 0 2 | for r in open(0): 3 | r = [*map(int, r.split())]; k = 0 4 | for i in range(len(r)+1): 5 | s = r[:i] + r[i+1:] 6 | z = [*zip(s, s[1:])] 7 | if all(0r+x>-1m[p]>0>d[p]:d[p]=d[r*L+c]+1;q.append((r+x,c+y)) 8 | if k==1023:print('Part 1:',d[-1]) 9 | if d[-1]==-1:print('Part 2:',S[k].strip());break -------------------------------------------------------------------------------- /aoc-2024/Day-13/Python/main.py: -------------------------------------------------------------------------------- 1 | import re; R = re.findall('Button A: X\+(\d+), Y\+(\d+)\nButton B: X\+(\d+), Y\+(\d+)\nPrize: X=(\d+), Y=(\d+)', open(0).read()) 2 | for p in (0, 1): 3 | Z = 0 4 | for r in R: 5 | a, d, b, e, c, f = map(int, r); c += p*10**13; f += p*10**13; x = c*d-a*f; y = b*d-a*e 6 | if x%y==0 and (c-x//y*b)%a==0: Z += 3*(c-x//y*b)//a+x//y 7 | print(f'Part {p+1}:', Z) -------------------------------------------------------------------------------- /aoc-2024/Day-22/Python/main.py: -------------------------------------------------------------------------------- 1 | Z=0;M=1<<24;X=[0]*M 2 | for x in map(int,open(0)): 3 | p = x%10; P = []; R = {} 4 | for _ in range(2000): 5 | x=(x<<6^x)%M; x=(x>>5^x)%M; x=(x<<11^x)%M 6 | P.append(x%10-p); p=x%10 7 | len(P) > 3 and R.setdefault(8000*P[-4]+400*P[-3]+20*P[-2]+P[-1], p) 8 | Z += x 9 | for i in R: X[i] += R[i] 10 | print('Part 1:',Z,'\nPart 2:',max(X)) -------------------------------------------------------------------------------- /aoc-2024/run_basilisk.py: -------------------------------------------------------------------------------- 1 | import os, time, sys 2 | d = int(sys.argv[1]) if len(sys.argv) > 1 else 1 3 | with open('basilisk.py') as f: lines = f.readlines() 4 | for day in range(d, 26): 5 | print(f'Day {day:02d}') 6 | t = time.time() 7 | os.system(f'''python3.8 -c "{lines[2*day-1].replace(chr(34),3*chr(39))}" < Day-{day:02d}/{day:02d}.in''') 8 | print(f'Time: {round(time.time()-t, 3)} seconds\n') -------------------------------------------------------------------------------- /aoc-2025/Day-06/Python/main.py: -------------------------------------------------------------------------------- 1 | l = [*open(0)] 2 | op = l[-1].split() 3 | p = [*zip(*([*map(int, s.split())] for s in l[:-1]))] 4 | q = ' '.join(map(''.join, zip(*l[:-1]))).split() 5 | print('Part 1:', sum(eval(y.join(map(str, x))) for x, y in zip(p, op))) 6 | x = [i for i in range(len(l[-1])) if l[-1][i] != ' '] + [len(l[-1])*2] 7 | print('Part 2:', sum(eval(op[i].join(q[x[i]-i:x[i+1]-1-i])) for i in range(len(op)))) -------------------------------------------------------------------------------- /aoc-2025/Day-12/Python/main.py: -------------------------------------------------------------------------------- 1 | *p, v = open(0).read().split('\n\n') 2 | Q = [] 3 | for i in range(len(p)): 4 | _, *m = p[i].split() 5 | Q.append(sum(r.count('#') for r in m)) 6 | Z = 0 7 | for k in v.split('\n'): 8 | R, C, *q = [*map(int, k[:(t:=k.find(':'))].split('x')+k[t+1:].split())] 9 | Z += R*C >= sum(Q[i]*v for i,v in enumerate(q)) 10 | print('Part 1:', Z) 11 | print('Part 2: THE END!') -------------------------------------------------------------------------------- /aoc-2025/run_basilisk.py: -------------------------------------------------------------------------------- 1 | import os, time, sys 2 | d = int(sys.argv[1]) if len(sys.argv) > 1 else 1 3 | with open('basilisk.py') as f: lines = f.readlines() 4 | for day in range(d, 13): 5 | print(f'Day {day:02d}') 6 | t = time.time() 7 | os.system(f'''python -W ignore -c "{lines[2*day-1].replace(chr(34),3*chr(39))}" < Day-{day:02d}/{day:02d}.in''') 8 | print(f'Time: {round(time.time()-t, 3)} seconds\n') -------------------------------------------------------------------------------- /aoc-2024/Day-11/Python/main.py: -------------------------------------------------------------------------------- 1 | m=[*map(int,input().split())];h={} 2 | def f(x,d): 3 | if d==0:return 1 4 | if(x,d)in h:return h[(x,d)] 5 | if x==0:h[(x,d)]=f(1,d-1);return h[(x,d)] 6 | y=str(x) 7 | if len(y)%2==0:h[(x,d)]=f(int(y[:len(y)//2]),d-1)+f(int(y[len(y)//2:]),d-1) 8 | else:h[(x,d)]=f(2024*x,d-1) 9 | return h[(x,d)] 10 | print('Part 1:',sum(f(i,25)for i in m)) 11 | print('Part 2:',sum(f(i,75)for i in m)) -------------------------------------------------------------------------------- /aoc-2023/Day-07/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys; from collections import * 2 | m = dict(zip('TJQKA', ':;<=>')) 3 | r = lambda f: [max(f), -len(f)] 4 | d = [*map(str.split, sys.stdin)] 5 | def solve(t): 6 | sd = sorted(d, key=lambda c: max(r(Counter(c[0].replace(t, i)).values()) for i in c[0])+[m.get(i, i) for i in c[0]]) 7 | return sum((i+1)*int(e[1]) for i,e in enumerate(sd)) 8 | print('Part 1:', solve('@')) 9 | m['J'] = '1'; print('Part 2:', solve('J')) -------------------------------------------------------------------------------- /aoc-2023/Day-09/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | s = t = 0 3 | def extrapolate(l): 4 | l = [l] 5 | for _ in l[0]: l.append([b-a for a,b in zip(l[-1], l[-1][1:])]) 6 | l[-1].append(0) 7 | for i in range(1, len(l)): l[-1-i].append(l[-1-i][-1]+l[-i][-1]) 8 | return l[0][-1] 9 | for l in sys.stdin: 10 | l = [*map(int, l.split())] 11 | s += extrapolate(l) 12 | t += extrapolate(l[::-1]) 13 | print('Part 1:', s) 14 | print('Part 2:', t) -------------------------------------------------------------------------------- /aoc-2023/Day-13/Python/main.py: -------------------------------------------------------------------------------- 1 | def solve(g, d): 2 | for i in range(1, len(g[0])): 3 | if sum(sum(a!=b for a,b in zip(r[i-1::-1], r[i:])) for r in g) == d: return i 4 | return 0 5 | 6 | import sys 7 | a = b = 0 8 | for l in ''.join(sys.stdin).strip().replace('\r', '').split('\n\n'): 9 | g = l.split('\n'); h = [*zip(*g)] 10 | a += solve(g, 0) + 100*solve(h, 0) 11 | b += solve(g, 1) + 100*solve(h, 1) 12 | print('Part 1:', a) 13 | print('Part 2:', b) -------------------------------------------------------------------------------- /aoc-2023/Day-06/Ruby/main.rb: -------------------------------------------------------------------------------- 1 | # Testing with ChatGPT 2 | def g(a, b) 3 | a - 1 - 2 * ((a - Math.sqrt(a * a - 4 * b)) / 2).to_i 4 | end 5 | 6 | data = [] 7 | 8 | 2.times do 9 | data << gets.split(/:\s+/)[1].split(/\s+/) 10 | end 11 | 12 | p = 1 13 | a = '' 14 | b = '' 15 | 16 | data[0].each_with_index do |x, i| 17 | y = data[1][i] 18 | p *= g(x.to_i, y.to_i) 19 | a += x 20 | b += y 21 | end 22 | 23 | puts "Part 1: #{p}" 24 | puts "Part 2: #{g(a.to_i, b.to_i)}" -------------------------------------------------------------------------------- /aoc-2024/Day-08/Python/main.py: -------------------------------------------------------------------------------- 1 | # Partly golfed 2 | import math;R=len(m:=[*open(0)]);C=len(m[-1]);N={};A=set();B=set() 3 | for i in range(R): 4 | for j in range(C):N[m[i][j]]=N.get(m[i][j],[])+[(i,j)] 5 | for i in N: 6 | if i>'.': 7 | for a,b in N[i]: 8 | for c,d in N[i]: 9 | x=a-c;y=b-d;e=c;f=d 10 | if x or y: 11 | g=math.gcd(x,y);x//=g;y//=g 12 | if R>c+2*x>-1e+x>-1= j[0] and j[1] >= r[-1][0]: r[-1] = (min(r[-1][0], j[0]), max(r[-1][1], j[1])) 5 | else: r.append(j) 6 | return r 7 | m = [*open(0)]; I = []; J = [] 8 | for i in m: 9 | if '-' in i: I += [[*map(int, i.split('-'))]] 10 | elif i.strip(): J += [int(i)] 11 | print('Part 1:', sum(any(x in range(a,b+1) for a,b in I)for x in J)) 12 | print('Part 2:', sum(b-a+1 for a,b in merge(I))) -------------------------------------------------------------------------------- /aoc-2023/Day-02/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | p1 = p2 = 0 3 | for l in sys.stdin: 4 | gid, c = l.strip().split(': ') 5 | gid = int(gid.split()[1]) 6 | h = {} 7 | for i in c.split('; '): 8 | for j in i.split(', '): 9 | q, n = j.split() 10 | if n not in h: h[n] = 0 11 | h[n] = max(h[n], int(q)) 12 | p1 += gid * (h['blue'] <= 14) * (h['green'] <= 13) * (h['red'] <= 12) 13 | p2 += h['blue'] * h['green'] * h['red'] 14 | print('Part 1:', p1) 15 | print('Part 2:', p2) -------------------------------------------------------------------------------- /aoc-2023/Day-08/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys, re; from math import * 2 | cmd = input().strip(); input(); g = {} 3 | for l in sys.stdin: 4 | a, b, c = re.findall('\w+', l) 5 | g[a] = [b, c] 6 | 7 | def dist(pos, dst, slc=0): 8 | t = 0 9 | while True: 10 | for i in cmd: t += 1; pos = g[pos][i>'L'] 11 | if pos[slc:] == dst: return t 12 | 13 | print('Part 1:', dist('AAA', 'ZZZ')) 14 | t = [dist(i, 'Z', -1) for i in g if i[-1] == 'A']; u = 1 15 | for i in t: u = (u*i)//gcd(u, i) 16 | print('Part 2:', u) -------------------------------------------------------------------------------- /aoc-2023/Day-01/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | t = u = 0 3 | m = dict(zip(['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', *map(str, range(1, 10))], [*range(1, 10)]*2)) 4 | n = [*m, *map(str, range(10))] 5 | for l in sys.stdin: 6 | s = [*map(int, filter(lambda x: x.isnumeric(), l))] 7 | t += 10*s[0] + s[-1] 8 | f = sorted(filter(lambda x: x[1]+1, {*((i, t(i)) for i in n for t in (l.find, l.rfind))}), key=lambda x: x[1]) 9 | u += 10*m[f[0][0]] + m[f[-1][0]] 10 | print('Part 1:', t) 11 | print('Part 2:', u) -------------------------------------------------------------------------------- /aoc-2024/Day-04/Python/main.py: -------------------------------------------------------------------------------- 1 | m = [*map(str.strip, open(0))] 2 | r = len(m); c = len(m[0]) 3 | a = b = 0 4 | for i in range(r): 5 | for j in range(c): 6 | for dr in range(-1, 2): 7 | for dc in range(-1, 2): 8 | if (dr or dc) and r>i+3*dr>-1 t: 12 | if u == t: ok = 1; break 13 | continue 14 | q.append((u*a[d], d+1)); q.append((u+a[d], d+1)) or p and q.append((int(f'{u}{a[d]}'), d+1)) 15 | z += ok*t 16 | return z 17 | 18 | print('Part 1:', run(0)) 19 | print('Part 2:', run(1)) -------------------------------------------------------------------------------- /aoc-2025/Day-04/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | m = [[*l.strip()] for l in sys.stdin] 3 | r = len(m); c = len(m[0]) 4 | p1 = p2 = 0 5 | while 1: 6 | bef = p2; M = [] 7 | for i in range(r): 8 | for j in range(c): 9 | z = 0 10 | if m[i][j] == '.': continue 11 | for di in range(-1, 2): 12 | for dj in range(-1, 2): 13 | if r>i+di>-1P!=[z[l].pop(),[[A(r,f-l+y,u[y]),A(u,y,P)]for y in Z(l)]]or[i:=i+1,q[2*i][0]>Pi],print(f'Part {t}:',S(i*j*(j>P)//2for i,j in G(S((v[::1-k%2*2]for k,v in G(q)),E))))];f(1);f(2) -------------------------------------------------------------------------------- /aoc-2024/Day-14/Python/main.py: -------------------------------------------------------------------------------- 1 | import re; L = len(M:=[*map(int, re.findall('[-\d]+', open(0).read()))]) 2 | 3 | R, C = 103, 101; B = (1, -1) 4 | for T in range(R*C): 5 | G = [['.']*C for _ in range(R)] 6 | Z = [0]*4 7 | for i in range(0, L, 4): 8 | py, px, vy, vx = M[i:i+4] 9 | x = (px+vx*T)%R; y = (py+vy*T)%C 10 | G[x][y] = '#' 11 | if x == R//2 or y == C//2: continue 12 | Z[(x B[0]: B = (t, T) 17 | if T == 100: print('Part 1:', Z[0]*Z[1]*Z[2]*Z[3]) 18 | print('Part 2:', B[1]) -------------------------------------------------------------------------------- /aoc-2023/Day-11/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | m = [*map(str.strip, sys.stdin)] 4 | def solve(e): 5 | R, C, G = len(m), len(m[0]), [] 6 | r, c = {*range(R)}, {*range(C)} 7 | for i in range(R): 8 | for j in range(C): 9 | if m[i][j] == '#': r.discard(i), c.discard(j), G.append((i, j)) 10 | p, q = [], []; t = u = 0 11 | for i in range(R): 12 | if i in r: t += e 13 | p.append(i+t) 14 | for i in range(C): 15 | if i in c: u += e 16 | q.append(i+u) 17 | return sum(abs(p[a]-p[c])+abs(q[b]-q[d]) for a,b in G for c,d in G)//2 18 | 19 | print('Part 1:', solve(1)) 20 | print('Part 2:', solve(10**6-1)) -------------------------------------------------------------------------------- /aoc-2025/Day-11/Python/main.py: -------------------------------------------------------------------------------- 1 | G = {} 2 | for l in open(0): 3 | x, *v = l.strip().split(); x = x[:-1] 4 | if x not in G: G[x] = [] 5 | for i in v: 6 | G[i] = G.get(i, []) 7 | G[x] = v 8 | I = {} 9 | for i in G: 10 | for j in G[i]: I[j] = I.get(j, 0)+1 11 | Q = [i for i in G if i not in I] 12 | for u in Q: 13 | for v in G[u]: I[v] -= 1; I[v] < 1 != Q.append(v) 14 | Z = {x:[1,0,0,0] for x in Q if not G[x]} 15 | while Q: 16 | u = Q.pop() 17 | Z[u] = Z.get(u, [0]*4) 18 | for v in G[u]: 19 | for i in range(4): Z[u][i|(u=='dac')|2*(u=='fft')] += Z[v][i] 20 | print('Part 1:', sum(Z.get('you', [0]*4))) 21 | print('Part 2:', Z.get('svr', [0]*4)[3]) -------------------------------------------------------------------------------- /aoc-2023/Day-12/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def solve(l, p): 4 | q = len(p); L = len(l); m = {} 5 | def f(i, j, c): 6 | if i==L: return (c==0 and j==q)or(c==p[-1] and j==q-1) 7 | k = (i, j, c) 8 | if k in m: return m[k] 9 | r = 0 10 | if l[i] > '#': 11 | if c == 0: r += f(i+1, j, 0) 12 | elif j < q and p[j] == c: r += f(i+1, j+1, 0) 13 | if l[i] != '.': r += f(i+1, j, c+1) 14 | m[k] = r; return r 15 | return complex(f(0, 0, 0), m[(4*L//5+1, 4*q//5, 0)]) 16 | 17 | a = 0 18 | for l in sys.stdin: 19 | l, p = l.split() 20 | a += solve('?'.join(5*[l]), 5*[*map(int, p.split(','))]) 21 | print('Part 1:', int(a.imag)) 22 | print('Part 2:', int(a.real)) -------------------------------------------------------------------------------- /aoc-2024/Day-12/Python/main.py: -------------------------------------------------------------------------------- 1 | m = ['@'+l.strip()+'@' for l in open(0)]; C = len(m[0]); m = ['@'*C]+m+['@'*C]; R = len(m); V = [0]*R*C; Z = Z2 = 0 2 | for i in range(1, R-1): 3 | for j in range(1, C-1): 4 | Q = [(i, j)]; A = P = 0; S = set(); E = 0 5 | for r, c in Q: 6 | if V[r*C+c]: continue 7 | V[r*C+c] = 1; A += 1 8 | for k, (dr, dc, t) in enumerate(((-1, 0, r), (0, -1, c), (0, 1, c), (1, 0, r))): 9 | if m[r][c]==m[r+dr][c+dc]: Q.append((r+dr, c+dc)) 10 | else: P += 1; S.add((k, t, r, c)) 11 | p = [-1]*3 12 | for t in sorted(S): 13 | E += t[:2] != p[:2] or abs(t[2]-p[2])+abs(t[3]-p[3]) != 1 14 | p = t 15 | Z += A*P; Z2 += A*E 16 | print('Part 1:', Z, '\nPart 2:', Z2) -------------------------------------------------------------------------------- /aoc-2025/Day-07/Python/main.py: -------------------------------------------------------------------------------- 1 | M = [l.strip() for l in open(0)] 2 | R, C = len(M), len(M[0]) 3 | S = set() 4 | Q = [(1, i) for i in range(len(M[0])) if M[0][i] == 'S'] 5 | D = {} 6 | for r, c in Q: 7 | if (r, c) in S or not R>r>-1sr>-1sr+dr>-1sr>-1sr+dr>-1r+dr>-1'8'}; A = B = 0 18 | for x in X: 19 | D = [0]*N; D[x] = 1 20 | for u in T[::-1]: 21 | for v in G[u]: D[u] += D[v] 22 | A += sum((D[i]>0)*(m[i//C][i%C]=='0')for i in range(N)) 23 | B += sum(D[i]*(m[i//C][i%C]=='0')for i in range(N)) 24 | print('Part 1:', A, '\nPart 2:', B) -------------------------------------------------------------------------------- /aoc-2025/Day-08/Python/main.py: -------------------------------------------------------------------------------- 1 | from heapq import * 2 | from math import * 3 | import sys 4 | 5 | P = [[*map(int, l.split(','))] for l in sys.stdin] 6 | N = len(P) 7 | 8 | Up = [*range(N)]; Urank = [0]*N; Usize = [1]*N; Un = [N] 9 | def find(i): 10 | if Up[i] == i: return i 11 | Up[i] = find(Up[i]) 12 | return Up[i] 13 | def union(i, j): 14 | if (x:=find(i)) != (y:=find(j)): 15 | Un[0] -= 1 16 | if Urank[x] > Urank[y]: Up[y] = x; Usize[x] += Usize[y] 17 | else: Up[x] = y; Urank[y] += Urank[x] == Urank[y]; Usize[y] += Usize[x] 18 | 19 | E = [(hypot(P[i][0]-P[j][0], P[i][1]-P[j][1], P[i][2]-P[j][2]), i, j) for i in range(N) for j in range(i)] 20 | heapify(E) 21 | k = 0 22 | while Un[0] > 1: 23 | _, a, b = heappop(E); union(a, b) 24 | if k == 999: 25 | *_, p, q, r = sorted(Usize[i] for i in {*map(find, range(N))}) 26 | print('Part 1:', p*q*r) 27 | k += 1 28 | print('Part 2:', P[a][0]*P[b][0]) -------------------------------------------------------------------------------- /aoc-2023/Day-03/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | m = [*map(lambda x: x.strip(), sys.stdin)] 3 | p1 = p2 = 0 4 | all_nums = set() 5 | for i in range(len(m)): 6 | for j in range(len(m[0])): 7 | if m[i][j] not in '0123456789.': 8 | nums = set() 9 | for di in range(-1, 2): 10 | for dj in range(-1, 2): 11 | if 0<=i+di= 0 and '0'<=m[i+di][k]<='9': k -= 1 14 | while l < len(m[0]) and '0'<=m[i+di][l]<='9': l += 1 15 | nums.add((i+di, k+1, l)) 16 | all_nums |= nums 17 | if m[i][j] == '*' and len(nums) == 2: 18 | (a, b, c), (d, e, f) = nums 19 | p2 += int(m[a][b:c])*int(m[d][e:f]) 20 | for i, j, k in all_nums: p1 += int(m[i][j:k]) 21 | print('Part 1:', p1) 22 | print('Part 2:', p2) -------------------------------------------------------------------------------- /aoc-2023/Day-16/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys 2 | m = [*map(str.strip, sys.stdin)]; b = [] 3 | for i in range(R:=len(m)): b.extend(((i, 0, 0), (i, (C:=len(m[0]))-1, 2))) 4 | for i in range(C): b.extend(((0, i, 3), (R-1, i, 1))) 5 | K = ((0, 1), (-1, 0), (0, -1), (1, 0)); m = ''.join(map(''.join, m)) 6 | 7 | def simulate(t): 8 | s = [t]; e = [0]*R*C; v = [0]*4*R*C 9 | while s: 10 | r, c, z = s.pop() 11 | if 0<=r a: k[v] = (a, min(z-1, b)); h[v] = (min(z, b+1), b); f += solve(k, w) 17 | if s == '>' and z < b: k[v] = (max(a, z+1), b); h[v] = (a, max(a-1, z)); f += solve(k, w) 18 | return f + solve(h, u[-1]) 19 | 20 | print('Part 1:', sum(map(lambda x: [t:=dict(zip('xmas', map(lambda x: [int(x)]*2, re.findall('\d+', x)))), sum(i[1] for i in t.values())*solve(t)][1], sys.stdin))) 21 | print('Part 2:', solve({i:(1,4000) for i in 'xmas'})) -------------------------------------------------------------------------------- /aoc-2024/Day-16/Python/main.py: -------------------------------------------------------------------------------- 1 | from heapq import *; INF = 1e18 2 | K=((0,-1),(-1,0),(1,0),(0,1));R=len(M:=[*open(0)]);C=len(M[-1]) 3 | for i in range(R): 4 | for j in range(C): 5 | if M[i][j]=='S': si, sj = i, j 6 | if M[i][j]=='E': ei, ej = i, j 7 | def dijkstra(Q, z): 8 | D = {x:0 for _,x in Q} 9 | while Q: 10 | t, (u, v, du, dv) = heappop(Q) 11 | if (u, v) == z: continue 12 | for di, dj in K: 13 | if (di, dj) != (du, dv) and M[u][v] > '#' and D.get(n:=(u, v, di, dj), INF) >= t+1000: D[n] = t+1000; heappush(Q, (D[n], n)) 14 | if M[u+du][v+dv] > '#' and D.get(n:=(u+du, v+dv, du, dv), INF) >= t+1: D[n] = t+1; heappush(Q, (D[n], n)) 15 | return D 16 | V = dijkstra([(0, (si, sj, 0, 1))], (ei, ej)) 17 | W = dijkstra([(0, (ei, ej, di, dj)) for di, dj in K], (si, sj)) 18 | Z = set() 19 | print('Part 1:', X:=min(V.get((ei, ej, di, dj), INF) for di, dj in K)) 20 | for i, j, di, dj in V: 21 | if V[(i, j, di, dj)]+W.get((i, j, -di, -dj), INF)==X: Z.add((i, j)) 22 | print('Part 2:', len(Z)) -------------------------------------------------------------------------------- /aoc-2024/Day-17/Python/main.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Assumptions: 3 | - the input starts with (2,4), has (7,5) in between, and ends with (3,0), and there's exactly one of each of these pairs 4 | - (0,3) and (5,5) appear somewhere between the (7,5) pair and (3,0) pair, in either order, and there's only one of each of these pairs 5 | - literally any remaining pair must be either (1,x) or (4,y), which are XOR operations, and none of these are after the (5,5) pair 6 | ''' 7 | 8 | import re 9 | a,b,c,*p=map(int,re.findall('\d+',open(0).read()));q=0;z=[];m={0};u=[0]*4;t=0 10 | 11 | while q>=x 14 | if i==1:b^=j;u[t]^=j 15 | if i==2:b=x%8 16 | if i==3:q=(j-2,q)[a==0];t|=2*(q<0) 17 | if i==4:b^=c 18 | if i==5:z.append(str(x%8)) 19 | if i==6:b=a>>x 20 | if i==7:c=a>>x;t|=j==5 21 | q+=2 22 | print('Part 1:',','.join(z)) 23 | for n in p[::-1]:m={y for x in m for k in range(8)if[y:=8*x+k,p:=y%8^u[0],(p^(y>>p)^u[1])%8==n][2]} 24 | print('Part 2:',min(m)) -------------------------------------------------------------------------------- /aoc-2024/Day-20/Python/main.py: -------------------------------------------------------------------------------- 1 | m = [[*x.strip()] for x in open(0)]; R = len(m); C = len(m[0]) 2 | K = ((0, 1), (0, -1), (-1, 0), (1, 0)); G = set() 3 | for i in range(R): 4 | for j in range(C): 5 | if m[i][j] == 'S': S = i*C+j; m[i][j] = '.' 6 | if m[i][j] == 'E': E = i*C+j; m[i][j] = '.' 7 | if m[i][j] == '.': G.add(i*C+j) 8 | 9 | def bfs(v): 10 | D = [-1]*R*C; D[v] = 0; Q = [v] 11 | for u in Q: 12 | r, c = divmod(u, C) 13 | for dr, dc in K: 14 | p = (r+dr)*C+c+dc 15 | if D[p] < 0 and m[r+dr][c+dc] == '.': D[p] = D[u]+1; Q.append(p) 16 | return D 17 | 18 | A = bfs(S); B = bfs(E); X = A[E] 19 | for p in range(2): 20 | Z = 0; Y = 2+18*p 21 | for i in G: 22 | ri, ci = divmod(i, C) 23 | for rj in range(max(ri-Y, 1), min(ri+Y+1, R)): 24 | d = Y-abs(ri-rj) 25 | for cj in range(max(ci-d, 1), min(ci+d+1, C)): 26 | if rj*C+cj in G: 27 | v = A[i]+B[rj*C+cj]+abs(ri-rj)+abs(ci-cj) 28 | if X-v >= 100: Z += 1 29 | print(f'Part {p+1}:', Z) -------------------------------------------------------------------------------- /aoc-2023/Day-17/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys; from heapq import *; from array import * 2 | 3 | def dijkstra(lb, ub): 4 | R = len(m) 5 | C = len(m[0]) 6 | D = array('i', [10**6]*4*R*C) 7 | K = ((0, 1), (-1, 0), (0, -1), (1, 0)) 8 | Z = ((1, 3), (0, 2))*2 9 | X = range(1, ub+1) 10 | pq = [] 11 | for s in range(4): D[s] = 0; heappush(pq, (0, s)) 12 | while pq: 13 | dd, tt = heappop(pq) 14 | r, c, z = tt//(4*C), tt//4%C, tt%4 15 | if dd != D[tt]: continue 16 | for i in Z[z]: 17 | rr, cc = r, c; dr, dc = K[i]; inc = 0 18 | for k in X: 19 | rr += dr; cc += dc 20 | if 0<=rr (nn:=dd+inc): D[t] = nn; heappush(pq, (nn, t)) 23 | else: 24 | break 25 | return min(D[4*R*C-i-1] for i in range(4)) 26 | 27 | m = [[*map(int, l.strip())] for l in sys.stdin] 28 | print('Part 1:', dijkstra(1, 3)) 29 | print('Part 2:', dijkstra(4, 10)) -------------------------------------------------------------------------------- /aoc-2024/Day-15/Python/main.py: -------------------------------------------------------------------------------- 1 | # partial golf, again 2 | Z=range;M,E=open(0).read().split('\n\n');M=[*map(list,M.split('\n'))];N=[[*''.join(map({'#':'##','O':'[]','.':'..','@':'@.'}.get,r))]for r in M] 3 | def do(M): 4 | R=len(M);C=len(M[0]) 5 | for i in Z(R): 6 | for j in Z(C): 7 | if M[i][j]=='@':r,c=i,j;M[i][j]='.' 8 | for i in E: 9 | for x,y,z in((0,-1,'<'),(0,1,'>'),(1,0,'v'),(-1,0,'^')): 10 | if i!=z:continue 11 | Q=[(r+x,c+y)];V=set() 12 | for p,q in Q: 13 | if M[p][q]not in'[]O'or(p,q)in V:continue 14 | V.add((p,q)) 15 | if M[p][q]=='[':Q.append((p,q+1)) 16 | elif M[p][q]==']':Q.append((p,q-1)) 17 | Q.append((p+x,q+y)) 18 | if(M[r+x][c+y]>'#')*all(M[p+x][q+y]>'#'for p,q in V): 19 | r+=x;c+=y;O={(p,q):M[p][q]for p,q in V} 20 | for p,q in O:M[p][q]='.' 21 | for p,q in O:M[p+x][q+y]=O[(p,q)] 22 | return sum(100*i+j for i in Z(R)for j in Z(C)if M[i][j]in'[O') 23 | print('Part 1:',do(M),'\nPart 2:',do(N)) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Russell Saerang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /aoc-2023/Day-05/Python/main.py: -------------------------------------------------------------------------------- 1 | def convert(s): 2 | s2 = [] 3 | for a, b in s: 4 | u = [] 5 | for p, q, r in d: 6 | if b < q or a > q+r-1: continue 7 | t = p-q; s2.append((max(a, q)+t, min(b, q+r-1)+t)), u.append((max(a, q), min(b, q+r-1))) 8 | if not u: s2.append((a, b)), u.append((a, b)) 9 | s2.append((a, u[0][0]-1)), u.insert(0, (a, u[0][0]-1)), s2.append((u[-1][1]+1, b)), u.append((u[-1][1]+1, b)) 10 | for i in range(len(u)-1): s2.append((u[i][1]+1, u[i+1][0]-1)), u.append((u[i][1]+1, u[i+1][0]-1)) 11 | return [(a, b) for a, b in s2 if a <= b] 12 | 13 | s = [*map(lambda x: [int(x)]*2, input().split(':')[1].split())]; input() 14 | s2 = sorted([s[2*i][0], s[2*i][0]+s[2*i+1][0]-1] for i in range(len(s)//2)) 15 | while True: 16 | try: c = input().split()[0]; d = [] 17 | except: break 18 | while True: 19 | try: e = [*map(int, input().split())] 20 | except: e = [] 21 | if not e: break 22 | d.append(e) 23 | d.sort(key=lambda x: x[1]); s = convert(s); s2 = convert(s2) 24 | print('Part 1:', min(s)[0]) 25 | print('Part 2:', min(s2)[0]) -------------------------------------------------------------------------------- /aoc-2023/Day-06/Java/Main.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | 4 | public class Main { 5 | static long g(long a, long b) { 6 | return a-1-2*(long)((a-Math.pow(a*a-4*b,0.5))/2); 7 | } 8 | 9 | public static void main(String args[]) throws IOException { 10 | BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 11 | PrintWriter writer = new PrintWriter(System.out); 12 | List> data = new ArrayList>(); 13 | for (int i = 0; i < 2; i++) { 14 | data.add(new ArrayList()); 15 | for (String s : br.readLine().split(":\\s+")[1].split("\\s+")) { 16 | data.get(i).add(s); 17 | } 18 | } 19 | long p = 1L; 20 | String a = "", b = ""; 21 | for (int i = 0; i < data.get(0).size(); i++) { 22 | String x = data.get(0).get(i), y = data.get(1).get(i); 23 | p *= g(Long.parseLong(x), Long.parseLong(y)); 24 | a += x; 25 | b += y; 26 | } 27 | writer.println("Part 1: " + p); 28 | writer.println("Part 2: " + g(Long.parseLong(a), Long.parseLong(b))); 29 | writer.flush(); 30 | } 31 | } -------------------------------------------------------------------------------- /aoc-2023/Day-22/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys, re, itertools 2 | 3 | # [-\d+] -> \d+ because there doesn't seem to be any negative number 4 | # min(x[2],x[5]) -> x[2] because L < R 5 | # range(min(a,b), max(a,b)+1) -> range(a,b+1) because of the above assumption 6 | 7 | B = {}; S = sorted(([*map(int, re.findall('\d+',l))] for l in sys.stdin), key=lambda x: x[2]) 8 | M = len(S); I = [0]*M 9 | 10 | # list cubes 11 | def lc(x1, y1, z1, x2, y2, z2): 12 | return itertools.product(range(x1, x2+1), range(y1, y2+1), range(z1, z2+1)) 13 | 14 | # count falls 15 | def cf(i): 16 | J = [*I]; s = [i]; d = -1 17 | for u in s: 18 | d += 1 19 | for v in G[u]: 20 | J[v] -= 1 21 | if J[v] == 0: s.append(v) 22 | return d 23 | 24 | # simulate dropping 25 | for i, j in enumerate(S): 26 | while j[2]: 27 | j[2] -= 1; j[5] -= 1 28 | if any(t in B and B[t] != i for t in lc(*j)): j[2] += 1; j[5] += 1; break 29 | for t in lc(*j): B[t] = i 30 | 31 | # connect supports 32 | G = [] 33 | for i in range(M): 34 | G.append({B[j] for *xy,z in lc(*S[i]) if (j:=(*xy,z+1)) in B and B[j] != i}) 35 | for j in G[i]: I[j] += 1 36 | 37 | print('Part 1:', sum(all(I[j]-1 for j in v) for v in G)) 38 | print('Part 2:', sum(map(cf, range(M)))) -------------------------------------------------------------------------------- /aoc-2023/Day-10/Python/main.py: -------------------------------------------------------------------------------- 1 | import sys; from collections import deque 2 | b = [*map(str.strip, sys.stdin)]; m = [['@']*(2*len(b[0])+1)] 3 | for l in b: m.append([*('@'+'@'.join(l)+'@')]), m.append(['@']*(2*len(b[0])+1)) 4 | R, C = len(m), len(m[0]) 5 | d = [-2]*R*C; k = ((0, -1), (0, 1), (-1, 0), (1, 0)); s = [(0, 0)] 6 | g = [[] for _ in range(R*C)] 7 | q = deque((C*i+j, 0) for i in range(R) for j in range(C) if m[i][j] == 'S') 8 | for r in range(R): 9 | for c in range(C): 10 | if m[r][c] in 'S|LJ': g[C*(r-1)+c].append(C*r+c), g[C*r+c].append(C*(r-1)+c) 11 | if m[r][c] in 'S|7F': g[C*(r+1)+c].append(C*r+c), g[C*r+c].append(C*(r+1)+c) 12 | if m[r][c] in 'S-LF': g[C*r+c+1].append(C*r+c), g[C*r+c].append(C*r+c+1) 13 | if m[r][c] in 'S-J7': g[C*r+c-1].append(C*r+c), g[C*r+c].append(C*r+c-1) 14 | while q: 15 | u, t = q.popleft() 16 | if d[u] < 0: 17 | d[u] = t; m[u//C][u%C] = '█' 18 | for v in g[u]: q.append((v, t+1)) 19 | while s: 20 | r, c = s.pop() 21 | if d[C*r+c] == -2: 22 | d[C*r+c] = -1; m[r][c] = ' ' 23 | for dr, dc in k: 24 | if 0<=r+dr ') 9 | if a == 'broadcaster': T[a] = -1 10 | elif a[0] == '%': a = a[1:]; T[a] = S[a] = 0 11 | else: a = a[1:]; T[a] = 1 12 | b = b.split(', '); G[a] = b 13 | for c in b: 14 | if c not in GT: GT[c] = {} 15 | GT[c][a] = 0 16 | z, tc = [0], [0]; src = [*GT['rx']]; H = {i:0 for i in sum([[*GT[i]] for i in src], [])} 17 | def push(): 18 | tc[0] += 1; q = deque([('broadcaster', 0, -1)]) 19 | while q: 20 | u, p, par = q.popleft() # u receives pulse p from par 21 | z[0] += complex(1-p, p) 22 | if u not in T: continue 23 | if T[u] == 0: 24 | if not p: S[u] ^= 1; q.extend((v, S[u], u) for v in G[u]) 25 | elif T[u] == 1: 26 | GT[u][par] = p; n = 1-int(all(GT[u].values())); q.extend((v, n, u) for v in G[u]) 27 | if u in src: 28 | for k, v in GT[u].items(): 29 | if v and H[k] == 0: H[k] = tc[0] 30 | else: 31 | q.extend((v, p, u) for v in G[u]) 32 | for _ in range(1000): push() 33 | print('Part 1:', int(z[0].real*z[0].imag)) 34 | while not all(H.values()): push() 35 | print('Part 2:', reduce(lambda x,y: x*y//gcd(x, y), H.values())) -------------------------------------------------------------------------------- /aoc-2024/Day-24/Python/main.py: -------------------------------------------------------------------------------- 1 | s,t=open(0).read().split('\n\n');Z=t.count(' z') 2 | T={} 3 | for x in t.split('\n'):a,b,c,_,d=x.split();T[(a,c,b)]=d 4 | F=lambda k,a,b,c:k==(a,b,c)or(b,a,c)==k 5 | M={} 6 | for i in s.split('\n'):M[i[:3]]=int(i[4:]) 7 | S=[];C='' 8 | def W(a,b):T[a],T[b]=T[b],T[a];S.extend((T[a],T[b])) 9 | for _ in T: 10 | for (a,c,b),d in T.items(): 11 | if a in M and c in M: 12 | if b=='XOR':M[d]=M[a]^M[c] 13 | if b=='OR':M[d]=M[a]|M[c] 14 | if b=='AND':M[d]=M[a]&M[c] 15 | print('Part 1:',sum(M[f'z{i:02}']< Mn 43 | Xn & Yn -> Nn 44 | C(n-1) & Mn -> Rn 45 | C(n-1) ^ Mn -> Zn # output 46 | Rn | Nn -> Cn # carry 47 | ''' -------------------------------------------------------------------------------- /aoc-2024/Day-21/Python/main.py: -------------------------------------------------------------------------------- 1 | from functools import *; from itertools import * 2 | N = '789456123X0A'; D = 'X^A'; RN = {e:i for i,e in enumerate(N)}; RD = {e:i for i,e in enumerate(D)} 3 | K = dict(zip('',((0,-1),(1,0),(-1,0),(0,1)))) 4 | A = {}; B = {} 5 | 6 | for (E, F, R) in ((A, D, 2), (B, N, 4)): 7 | for ri in range(R): 8 | for ci in range(3): 9 | if F[3*ri+ci] == 'X': continue 10 | for rj in range(R): 11 | for cj in range(3): 12 | if F[3*rj+cj] == 'X': continue 13 | if cj>=ci: p = '>'*(cj-ci) 14 | else: p = '<'*(ci-cj) 15 | if rj>=ri: p += 'v'*(rj-ri) 16 | else: p += '^'*(ri-rj) 17 | E[F[3*ri+ci]+F[3*rj+cj]] = p 18 | 19 | @lru_cache 20 | def f(s, n, t=0): 21 | if n == 0: return len(s) 22 | s = 'A'+s; z = 0 23 | for i in range(len(s)-1): 24 | P = []; x = (B, A)[t][s[i]+s[i+1]]; r, c = divmod((RN, RD)[t][s[i]], 3) 25 | for p in {*permutations(x)}: 26 | rr, cc = r, c; ok = 1 27 | for q in p: 28 | dr, dc = K[q]; rr += dr; cc += dc 29 | if not 4-2*t>rr>-1'), (1, 0, 'v'), (-1, 0, '^')) 4 | F = [{} for _ in range(n)]; G = [{} for _ in range(n)] 5 | for rr in range(R): 6 | for cc in range(C): 7 | if m[rr][cc] == '#': continue 8 | curr = rr*C+cc 9 | for dr, dc, z in K: 10 | if 0<=rr+dr flow and d[v] == -1: 22 | d[v] = d[u]+1 23 | q.append(v) 24 | return d[t] != -1 25 | 26 | def DFS(u, t, f=INF): 27 | if u == t or f == 0: return f 28 | for i in range(last[u], len(AL[u])): 29 | last[u] = i 30 | v, cap, flow = EL[AL[u][i]] 31 | if d[v] != d[u]+1: continue 32 | pushed = DFS(v, t, min(f, cap - flow)) 33 | if pushed: 34 | EL[AL[u][i]][2] += pushed 35 | EL[AL[u][i]^1][2] -= pushed 36 | return pushed 37 | return 0 38 | 39 | EL, AL = [], [[] for _ in range(V)] 40 | for i in g: 41 | for j in g[i]: EL.append([r[j], 1, 0]), AL[r[i]].append(len(EL)-1), EL.append([r[i], 1, 0]), AL[r[j]].append(len(EL)-1) 42 | for source in range(V): 43 | for sink in range(source+1, V): 44 | mf = 0; d = [-1]*V 45 | for e in EL: e[2] = 0 46 | while BFS(source, sink): 47 | last = [0]*V; f = DFS(source, sink) 48 | while f: mf += f; f = DFS(source, sink) 49 | d = [-1]*V 50 | if mf == 3: 51 | c = sum(i!=-1 for i in d) 52 | print('Part 1:', c*(V-c)) 53 | print('Part 2: THE END!'), exit(0) -------------------------------------------------------------------------------- /aoc-2025/Day-09/Python/main.py: -------------------------------------------------------------------------------- 1 | def pip(p): 2 | z = False; n = len(P) 3 | for i in range(n): 4 | a = (P[i][0]-p[0], P[i][1]-p[1]); b = (P[(i+1)%n][0]-p[0], P[(i+1)%n][1]-p[1]) 5 | if a[1] > b[1]: a, b = b, a 6 | if a[1] <= 0 and b[1] > 0 and a[0]*b[1] < a[1]*b[0]: z = not z 7 | if a[0]*b[1] == a[1]*b[0] and a[0]*b[0]+a[1]*b[1] <= 0: return True 8 | return z 9 | 10 | # ray tracing? 11 | def pip2(p): 12 | for i in range(len(poly)-1): 13 | if abs(dist(poly[i], p) + dist(p, poly[i+1]) - dist(poly[i], poly[i+1])) < 1e-9: return True 14 | ray = (p, (p[0]+1e9, p[1]+1e9+7)) 15 | return bool(sum(intersect_check(ray, (poly[i], poly[i+1])) for i in range(len(poly)-1))%2) 16 | 17 | def its(s1, s2): 18 | (p1, p2), (p3, p4) = s1, s2; (x1, y1), (x2, y2), (x3, y3), (x4, y4) = p1, p2, p3, p4 19 | c1 = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1); c2 = (x2-x1)*(y4-y1)-(y2-y1)*(x4-x1) 20 | if (c1 <= 0 and c2 <= 0) or (c1 >= 0 and c2 >= 0): return 0 21 | c1 = (x4-x3)*(y1-y3)-(y4-y3)*(x1-x3); c2 = (x4-x3)*(y2-y3)-(y4-y3)*(x2-x3) 22 | if (c1 <= 0 and c2 <= 0) or (c1 >= 0 and c2 >= 0): return 0 23 | return 1 24 | 25 | P = [[*map(int, l.split(','))] for l in open(0)] 26 | print('Part 1:', max(-~abs(c-a)*-~abs(d-b) for a,b in P for c,d in P)) 27 | Z = 0 28 | for a,b in P: 29 | for c,d in P: 30 | if -~abs(c-a)*-~abs(d-b) <= Z: continue 31 | bad = 0 32 | for s in (((a, b), (a, d)), ((a, d), (c, d)), ((c, d), (c, b)), ((c, b), (a, b))): 33 | if not pip(s[0]) or not pip(s[1]): # check if the midpoint is also outside the polygon to be more accurate, but I think this will work for the input shape 34 | bad = 1; break 35 | for i in range(len(P)): 36 | if its(s, (P[i], P[i-1])): 37 | bad = 1; break 38 | if bad: break 39 | if not bad: 40 | Z = -~abs(c-a)*-~abs(d-b) 41 | print('Part 2:', Z) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advent of Code 2 | Collection of my Advent of Code (AOC) repositories. For codes before 2023, tap on the cards to redirect you to the respective repository! 3 | 4 | [![2015](https://github-readme-stats.vercel.app/api/pin/?theme=react&username=RussellDash332&repo=aoc-2015)](https://github.com/RussellDash332/aoc-2015) 5 | [![2016](https://github-readme-stats.vercel.app/api/pin/?theme=highcontrast&username=RussellDash332&repo=aoc-2016)](https://github.com/RussellDash332/aoc-2016) 6 | [![2017](https://github-readme-stats.vercel.app/api/pin/?theme=omni&username=RussellDash332&repo=aoc-2017)](https://github.com/RussellDash332/aoc-2017) 7 | [![2018](https://github-readme-stats.vercel.app/api/pin/?theme=great-gatsby&username=RussellDash332&repo=aoc-2018)](https://github.com/RussellDash332/aoc-2018) 8 | [![2019](https://github-readme-stats.vercel.app/api/pin/?theme=chartreuse-dark&username=RussellDash332&repo=aoc-2019)](https://github.com/RussellDash332/aoc-2019) 9 | [![2020](https://github-readme-stats.vercel.app/api/pin/?theme=gotham&username=RussellDash332&repo=aoc-2020)](https://github.com/RussellDash332/aoc-2020) 10 | [![2021](https://github-readme-stats.vercel.app/api/pin/?theme=monokai&username=RussellDash332&repo=aoc-2021)](https://github.com/RussellDash332/aoc-2021) 11 | [![2022](https://github-readme-stats.vercel.app/api/pin/?theme=react&username=RussellDash332&repo=aoc-2022)](https://github.com/RussellDash332/aoc-2022) 12 | 13 | ## Note to Self 14 | ```sh 15 | export X=... # day number, 2 digits 16 | export Y=... # year 17 | 18 | # Note that .in files are hidden but it should be within Day-/.in 19 | 20 | # Python 21 | cd ~/advent-of-code/aoc-$Y/Day-$X/Python && python main.py < ../$X.in && cd ../../.. 22 | 23 | # JavaScript 24 | cd ~/advent-of-code/aoc-$Y/Day-$X/JavaScript && node main.js < ../$X.in && cd ../../.. 25 | 26 | # Java 27 | cd ~/advent-of-code/aoc-$Y/Day-$X/Java && javac Main.java && java Main < ../$X.in && cd ../../.. 28 | 29 | # C++ 30 | cd ~/advent-of-code/aoc-$Y/Day-$X/C++ && g++ -o mainc main.cpp && ./mainc < ../$X.in && cd ../../.. 31 | 32 | # Haskell 33 | cd ~/advent-of-code/aoc-$Y/Day-$X/Haskell && runhaskell main.hs && cd ../../.. 34 | 35 | # Rust 36 | cd ~/advent-of-code/aoc-$Y/Day-$X/Rust && rustc main.rs && ./main < ../$X.in && cd ../../.. 37 | 38 | # Ruby 39 | cd ~/advent-of-code/aoc-$Y/Day-$X/Ruby && ruby main.rb < ../$X.in && cd ../../.. 40 | ``` -------------------------------------------------------------------------------- /aoc-2025/Day-10/Python/main.py: -------------------------------------------------------------------------------- 1 | INF = float('inf'); EPS = 1e-9 2 | def simplex(A, C): 3 | def pivot(r, s): 4 | k = 1/D[r][s] 5 | for i in range(m+2): 6 | if i == r: continue 7 | for j in range(n+2): 8 | if j != s: D[i][j] -= D[r][j]*D[i][s]*k 9 | for i in range(n+2): D[r][i] *= k 10 | for i in range(m+2): D[i][s] *= -k 11 | D[r][s] = k; B[r], N[s] = N[s], B[r] 12 | def find(p): 13 | while True: 14 | if D[m+p][s:=min((i for i in range(n+1) if p or N[i] != -1), key=lambda x: (D[m+p][x], N[x]))] > -EPS: return 1 15 | if (r:=min((i for i in range(m) if D[i][s] > EPS), key=lambda x: (D[x][-1]/D[x][s], B[x]), default=-1)) == -1: return 0 16 | pivot(r, s) 17 | m = len(A); n = len(A[0])-1; N = [*range(n), -1]; B = [*range(n, n+m)]; D = [*([*A[i], -1] for i in range(m)), C+[0]*2, [0]*(n+2)] 18 | for i in range(m): D[i][-2], D[i][-1] = D[i][-1], D[i][-2] 19 | D[-1][n] = 1; r = min(range(m), key=lambda x: D[x][-1]) 20 | if D[r][-1] < -EPS and (pivot(r, n) or not find(1) or D[-1][-1] < -EPS): 21 | return -INF, None 22 | for i in range(m): B[i] == -1 and pivot(i, min(range(n), key=lambda x: (D[i][x], N[x]))) 23 | if find(0): 24 | x = [0]*n 25 | for i in range(m): 26 | if 0 <= B[i] < n: x[B[i]] = D[i][-1] 27 | return sum(C[i]*x[i] for i in range(n)), x 28 | else: 29 | return -INF, None 30 | 31 | def f(A): 32 | n = len(A[0])-1 33 | bval = float('inf') 34 | bsol = None 35 | def branch(A): 36 | nonlocal bval, bsol 37 | 38 | val, x = simplex(A, [1]*n) 39 | if val+EPS >= bval or val == -INF: 40 | return 41 | 42 | k, v = next(((i, int(e)) for i,e in enumerate(x) if abs(e-round(e))>EPS), (-1, 0)) 43 | if k == -1: 44 | if val+EPS < bval: 45 | bval, bsol = val, [*map(round, x)] 46 | else: 47 | s = [0]*n+[v]; s[k] = 1 48 | branch(A+[s]) 49 | s = [0]*n+[~v]; s[k] = -1 50 | branch(A+[s]) 51 | branch(A) 52 | return round(bval) 53 | 54 | p1 = p2 = 0 55 | for l in open(0): 56 | m, *p, c = l.split() 57 | n = len(m)-2 58 | q = [*map(lambda x: eval(x[:-1]+',)'), p)] 59 | c = [*map(int, c[1:-1].split(','))] 60 | 61 | # Part 1: bitmask BFS 62 | B = [-1]*(1< 0 and t2 > 0 and lb <= px1+vx1*t <= ub and lb <= py1+vy1*t <= ub 10 | ''' 11 | To solve for (PX, PY, PZ, VX, VY, VZ), we have the following system of equations (uppercase variables are unknown) 12 | (PX + VX * Ti, PY + VY * Ti, PZ + VZ * Ti) = (pxi + vxi * Ti, pyi + vyi * Ti, pzi + vzi * Ti) 13 | -> PX + VX * Ti = pxi + vxi * Ti -> PX - pxi = (vxi - VX) * Ti -> (1) 14 | -> PY - pyi = (vyi - VY) * Ti -> (2) 15 | (1) * (vyi - VY) - (2) * (vxi - VX) 16 | -> (PX - pxi) * (vyi - VY) - (PY - pyi) * (vxi - VX) = 0 17 | -> PY * VX - PX * VY + vyi * PX + pxi * VY - pyi * VX - vxi * PY + (pyi * vxi - pxi * vyi) = 0 (3) 18 | -> PY * VX - PX * VY + vyj * PX + pxj * VY - pyj * VX - vxj * PY + (pyj * vxj - pxj * vyj) = 0 (4, i => j) 19 | (3) - (4) 20 | -> (vyi - vyj) * PX + (pxi - pxj) * VY - (pyi - pyj) * VX - (vxi - vxj) * PY + (pyi * vxi - pxi * vyi - pyj * vxj + pxj * vyj) = 0 21 | -> (vzi - vzj) * PX + (pxi - pxj) * VZ - (pzi - pzj) * VX - (vxi - vxj) * PZ + (pzi * vxi - pxi * vzi - pzj * vxj + pxj * vzj) = 0 22 | ''' 23 | if len(A) != 6: 24 | A.append([vy1-vy2, vx2-vx1, 0, py2-py1, px1-px2, 0, px1*vy1+py2*vx2-py1*vx1-px2*vy2]) 25 | A.append([vz1-vz2, 0, vx2-vx1, pz2-pz1, 0, px1-px2, px1*vz1+pz2*vx2-pz1*vx1-px2*vz2]) 26 | 27 | # https://github.com/RussellDash332/pytils/blob/main/rref.py 28 | for i in range(len(A)): 29 | for j in range(len(A[0])): A[i][j] = Fraction(A[i][j]) 30 | def equal(a, b): 31 | return a == b 32 | def leading_entry_col(A, r): 33 | row = A[r]; i = 0 34 | while i < len(A[0]) and equal(row[i], 0): i += 1 35 | return i 36 | def list_pivots(A): 37 | res = [] 38 | for r in range(len(A)): 39 | k = leading_entry_col(A, r) 40 | if k != len(A[0]): res.append((r, k)) 41 | return sorted(res, reverse=True) 42 | def col(A, i): 43 | return list(map(lambda x: x[i], A)) 44 | def ero1(A, i, c): 45 | for j in range(len(A[0])): A[i][j] *= c 46 | def ero2(A, i, j, c): 47 | for k in range(len(A[0])): A[i][k] += c*A[j][k] 48 | def ero3(A, i, j): A[i], A[j] = A[j], A[i] 49 | curr_col = 0 50 | curr_row = 0 51 | while curr_col < len(A[0]) and curr_row < len(A): 52 | if equal(A[curr_row][curr_col], 0): 53 | check_col = col(A, curr_col)[curr_row+1:] 54 | for i in range(len(check_col)): 55 | if not equal(check_col[i], 0): break 56 | elif i == len(check_col)-1: i += 1 57 | if i < len(check_col): ero3(A, curr_row, curr_row+i+1) 58 | else: curr_col += 1 59 | else: 60 | if not equal(A[curr_row][curr_col], 1): ero1(A, curr_row, 1/A[curr_row][curr_col]) 61 | for i in range(curr_row+1, len(A)): 62 | if not equal(A[i][curr_col], 0): ero2(A, i, curr_row, -A[i][curr_col]) 63 | curr_col += 1 64 | curr_row += 1 65 | pivots = list_pivots(A) 66 | for i in range(len(pivots)-1): 67 | for j in range(pivots[i][0]-1, -1, -1): ero2(A, j, pivots[i][0], -A[j][pivots[i][1]]) 68 | 69 | print('Part 1:', ans) 70 | print('Part 2:', A[0][6]+A[1][6]+A[2][6]) -------------------------------------------------------------------------------- /aoc-2025/basilisk.py: -------------------------------------------------------------------------------- 1 | # Day 01: 142 2 | p=50;q=[[p:=(p+2*(x>'Q')-1)%100for _ in'.'*int(x[1:])]for x in open(0)];print('Part 1:',sum(r[-1]<1for r in q),'\nPart 2:',sum(q,[]).count(0)) 3 | # Day 02: 196 4 | import re;v=[[*map(int,l.split('-'))]for l in input().split(',')];f=lambda t:sum(i for a,b in v for i in range(a,b+1)if re.match(rf'^(\d+)\1{t}$',str(i)));print('Part 1:',f(''),'\nPart 2:',f('+')) 5 | # Day 03: 187 6 | from functools import*;f=cache(lambda x,n:max(f(y:=x//10,n),10*f(y,n-1)+x%10)if x*n else 0);v=[*map(int,open(0))];print('Part 1:',sum(f(x,2)for x in v),'\nPart 2:',sum(f(x,12)for x in v)) 7 | # Day 04: 299 8 | R=range;r=len(m:=[*map(list,open(0))]);c=len(m[0])-1;P=[0];[[q:=len(M:=[(i,j)for i in R(r)for j in R(c)if'.'i+x>-1'.'for x in R(-1,2)for y in R(-1,2))<5]),[m[i].__setitem__(j,'.')for i,j in M],q and P.append(q)]for p in P];print('Part 1:',P[1],'\nPart 2:',sum(P)) 9 | # Day 05: 295 10 | S,M=str.split,[];A,B=S(open(0).read(),'\n\n');[M.append(M and(a:=M[-1])[1]>=j[0]<=j[1]>=a[0]and[M.pop(),min(a[0],j[0]),max(a[1],j[1])][1:]or j)for j in sorted([*map(int,S(i,'-'))]for i in S(A))];print('Part 1:',sum(any(a<=int(q)'S',T:=T|{v:T.get(v,0)+Q[k]for v in(k-x,k+x)}][0]for k in Q),Q:=T][1]for r in M]),'\nPart 2:',sum(Q.values())) 15 | # Day 08: 355 16 | R=range(len(P:=[[*map(int,l.split(','))]for l in open(0)]));T=z=[1<((g-e)*(b-f)-(h-f)*(a-e))*((g-e)*(d-f)-(h-f)*(c-e));Z=sorted((~D(c-a)*-~D(d-b),a,b,c,d)for a,b in P for c,d in P);print('Part 1:',-Z[0][0],'\nPart 2:',next(-w for w,a,b,c,d in Z if[K:=[(a,b),(a,d),(c,d),(c,b)],z:=all(map(C,K)),[z:=z*~-I(*K[k],*K[k-1],*P[i],*P[i-1])for i in R for k in(0,1,2,3)if z],z][3])) 19 | # Day 10: 1569 20 | g=lambda A:[P:=lambda r,s:[k:=1/D[r][s],[j!=s!=F(D[i],j,D[i][j]-D[r][j]*D[i][s]*k)for i in R(m+2)if i-r for j in R(N+2)],[F(D[r],i,D[r][i]*k)for i in R(N+2)],[F(D[i],s,D[i][s]*-k)for i in R(m+2)],F(D[r],s,k),t:=C[r],F(C,r,Y[s]),F(Y,s,t)],W:=lambda p:-1if-EE]or[-1],key=lambda x:(D[x][-1]/D[x][s],C[x])))==-1else P(r,s)and W(p),m:=len(A),Y:=[*R(N),-1],C:=[*R(N,N+m)],D:=[*([*a[:-1],-1,a[-1]]for a in A),[1]*N+[0]*2,[*[0]*N,1,0]],X:=(I,0)if-E>D[r:=M(R(m),key=lambda x:D[x][-1])][-1]and(P(r,N)and~W(1)or-E>D[-1][-1])else[[~C[i]or P(i,M(R(N),key=lambda x:(D[i][x],Y[x])))for i in R(m)],(I,0)if~W(0)else[x:=[0]*N,[F(x,C[i],D[i][-1])for i in R(m)if C[i]E),(-1,0)),k:=T[0],v:=T[1],[F(s:=[0]*N+[v],k,1),F(t:=[0]*N+[~v],k,-1),M(g(A+[s]),g(A+[t]))][2]if~k else X[0]][3]if x else I][8];I=1e9;E=1/I;M=min;R=range;F=list.__setitem__;Z=sum([[L:=l.split(),n:=len(c:=eval(f'[{L[-1][1:-1]}]')),q:=[eval(x[:-1]+',)')for x in L[1:-1]],B:=[0]+[-1]*2**n,p:=[sum(1<1);print('Part 1:',z('you',2),'\nPart 2:',z('svr',0)) 23 | # Day 12: 161 24 | import re;O=[*open(0)][::-1];print('Part 1:',sum((K:=[*map(int,re.findall('\d+',i))])and K[0]*K[1]>=9*sum(K[2:])for i in O[:O.index('\n')]),'\nPart 2: THE END!') -------------------------------------------------------------------------------- /aoc-2024/basilisk.py: -------------------------------------------------------------------------------- 1 | # Day 01: 148 2 | a,b=map(sorted,zip(*(map(int,x.split())for x in open(0))));print('Part 1:',sum(abs(x-y)for x,y in zip(a,b)),'\nPart 2:',sum(x*b.count(x)for x in a)) 3 | # Day 02: 232 4 | a=[[*map(int,r.split())]for r in open(0)];f=lambda t:sum(any((z:=[*zip(s:=r[:i]+r[i+1:],s[1:])])*(all(0i//c+3*p>-1a>-1a+v>-1m[a+v][b+w]],l:=l|((t:=(a,b,a:=a+v,b:=b+w))in d),d.add(t)]for _ in R],[d,l][p]][5];print('Part 1:',len(D:={u[:2]for u in s(0)}),'\nPart 2:',sum([S(m[a],b,'#'),s(1),S(m[a],b,'.')][1]for a,b in D)) 13 | # Day 07: 265 14 | m=[*open(0)];f=lambda i,c,k,t,p:f(i+1,c+k[i],k,t,p)or f(i+1,c*k[i],k,t,p)or~-p*f(i+1,int(f'{c}{k[i]}'),k,t,p)if i-len(k)else c==t;z=lambda p:print(f'Part {p}:',sum([u:=l.split(':'),t:=int(u[0]),k:=[*map(int,u[1].split())],t*f(1,k[0],k,t,p)][3]for l in m));z(1);z(2) 15 | # Day 08: 385 16 | import math;Z=range;R=len(m:=[*open(0)]);C=len(m[-1]);N={};A=set();B=set();[[(x:=m[i][j])>'.'!=N.update({x:N.get(x,[])+[(i,j)]})]for i in Z(R)for j in Z(C)];[[g:=math.gcd(x,y),x:=x//g,y:=y//g,e:=c,f:=d,[[B.add(t:=(e:=e+x,f:=f+y)),k==1!=A.add(t)]for k in Z(R+C)if R>e+x>-1q.pop()for _ in Z(9)]+[k:=r[i],l:=0,[[[[a(k-m+1+j,P),a(p+j,i),r.update({i:r[i]-1}),d:=p]for j in Z(m)],l:=P]for p in Z(d*t,r[i])if[P]*m==q[p:p+m]and~l]]for _ in Z(s[2*i]//m)]for i in Z(max(q),P,P)],print(f'Part {2-t}:',sum(i*j*(j>P)for i,j in G(q)))];f(1);f(0) 19 | # Day 10: 557 20 | E=list.append;S=list.__setitem__;R=len(m:=[*open(0)]);C=len(m[-1]);Z=range(N:=R*C);G=[[]for _ in Z];I=[0]*N;T=[];[[r:=i//C,c:=i%C,R>r+p>-10,D[i]][p]for i in Z if'1'>m[i//C][i%C])][3]for x in Z if'8'1),S:=t]for t in sorted(S)],X:=X+A*P,Y:=Y+A*E]for i in Z(1,R-1)for j in Z(1,C-1)];print('Part 1:',X,'\nPart 2:',Y) 25 | # Day 13: 254 26 | import re;R=[*map(int,re.findall('\d+',open(0).read()))];[print(f'Part {p+1}:',sum([a:=R[i:i+6],b:=a[0],c:=a[4]+(u:=p*10**13),(x:=c*a[1]-b*a[5]-b*u)%(y:=a[2]*a[1]-b*a[3])==(d:=c-x//y*a[2])%b==0and d*3//b+x//y][3]for i in range(0,len(R),6)))for p in(0,1)] 27 | # Day 14: 306 28 | import re;M=[*map(int,re.findall('[-\d]+',open(0).read()))];U=[[Z:=[0]*4,[[p:=M[i:i+4],x:=(p[1]+p[3]*T)%103,y:=(p[0]+p[2]*T)%101,Z.__setitem__(b:=(x<51)+2*(y<50),Z[b]+(x!=51!=y+1))]for i in range(0,len(M),4)],(Z[0]*Z[1]*Z[2]*Z[3],T)][2]for T in range(5**6)];print('Part 1:',U[100][0],'\nPart 2:',min(U)[1]) 29 | # Day 15: 760 30 | Z=range;U,E=open(0).read().split('\n\n');U=[*map(list,U.split())];N=[[*''.join(map({'#':'##','O':'[]','.':'..','@':'@.'}.get,r))]for r in U];A=list.__setitem__;F=lambda M:[R:=len(M),C:=len(M[0]),s:=min(i for i in Z(R*C)if'@'==M[i//C][i%C]),r:=s//C,c:=s%C,[i==z and[Q:=[(r+x,c+y)],B:=Q.append,V:=set(),[M[p][q]in'[]O'and(p,q)not in V and(V.add((p,q)),B((p,q-1))if'[''#')*all(M[p+x][q+y]>'#'for p,q in V)and[r:=r+x,c:=c+y,O:={(p,q):M[p][q]for p,q in V},[A(M[p],q,'.')for p,q in O],[A(M[p+x],q+y,O[(p,q)])for p,q in O]]]for i in E for x,y,z in((0,-1,'<'),(0,1,'>'),(1,0,'v'),(-1,0,'^'))],sum(j+i*100for i in Z(R)for j in Z(C)if M[i][j]in'[O')][6];print('Part 1:',F(U),'\nPart 2:',F(N)) 31 | # Day 16: 679 32 | from heapq import*;L=9e9;U=range;P=heappush;K=((0,-1),(-1,0),(1,0),(0,1));R=len(M:=[*open(0)]);C=len(M[-1]);S,E=(min((i,j)for i in U(R)for j in U(C)if M[i][j]==c)for c in'SE');F=lambda Q,z:[D:={tuple(x):0for _,*x in Q},J:=D.__setitem__,[[p:=heappop(Q),t:=p[0],u:=p[1],v:=p[2],w:=p[3],r:=K[w][0],c:=K[w][1],(u,v)!=z!=[[i-w!=M[u][v]>'#'!=D.get(n:=(u,v,i),L)>t+999!=J(n,t+1000)!=P(Q,(D[n],*n))for i in U(4)],M[u+r][v+c]>'#'!=D.get(n:=(u+r,v+c,w),L)>t!=J(n,t+1)!=P(Q,(D[n],*n))]]for _ in U(R*C*12)if Q]][0];V=F([(0,*S,3)],E);W=F([(0,*E,i)for i in U(4)],S);print('Part 1:',X:=min(V.get((*E,i),L)for i in U(4)),'\nPart 2:',len({tuple(p)for*p,x in V if V[(*p,x)]+W.get((*p,x^3),L)==X})) 33 | # Day 17: 480 34 | import re;a,b,c,*p=map(int,re.findall('\d+',open(q:=0).read()));m={0};u=[t:=0]*4;[q>x]or i<2!=(b:=b^j,u.__setitem__(t,u[t]^j))or i%2<1!=[b:=(x%8,b^c)[i//4]]or i<4!=(q:=(j-2,q)[a<1],t:=t|2*(q<0))or i>6!=(c:=a>>x,t:=t|1)or u.append(str(x%8)),q:=q+2]for _ in'.'*999];print('Part 1:',','.join(u[4:]),'\nPart 2:',min([m:={y for x in m for k in range(8)if[y:=8*x+k,w:=y%8^u[0],(y>>w)%8^w^u[1]==n][2]}for n in p[::-1]][-1])) 35 | # Day 18: 358 36 | S=[*open(0)];L=71;m=L*L*[1];d=[[0]+L*L*[-1]for _ in S];F=list.__setitem__;X=S[sum([t:=[*map(int,r.split(','))],F(m,t[1]*L+t[0],0),q:=[(0,0)],[L>r+x>-1m[(p:=(r+x)*L+c+y)]>0>D[p]!=F(D,p,D[r*L+c]+1)!=q.append((r+x,c+y))for r,c in q for x,y in((0,-1),(-1,0),(0,1),(1,0))],D[-2]>0][4]for r,D in zip(S,d))].strip();print('Part 1:',d[1023][-2],'\nPart 2:',X) 37 | # Day 19: 220 38 | from functools import*;P,_,*m=map(str.strip,open(0));P=P.split(', ');f=lru_cache(lambda s:(s in P)+sum(f(s[i:])*(s[:i]in P)for i in range(1,len(s))));print("Part 1:",len(v:=[x for i in m if(x:=f(i))]),"\nPart 2:",sum(v)) 39 | # Day 20: 579 40 | U=range;R=len(m:=[[*x.strip()]for x in open(0)]);C=len(m[0]);N=R*C;K=((0,1),(0,-1),(-1,0),(1,0));S,E=(min(i for i in U(N)if m[i//C][i%C]==c)for c in'SE');A=[-1]*N;B=[*A];A[S]=B[E]=0;[[Q:=[v],[[r:=u//C,c:=u%C,[D[(p:=(r+x)*C+c+y)]<0!=m[r+x][c+y]>'#'!=D.__setitem__(p,D[u]+1)!=Q.append(p)for x,y in K]]for u in Q]]for D,v in((A,S),(B,E))];[[Y:=2+18*p,print(f'Part {p+1}:',sum(sum([d:=Y-abs(a-s),sum(m[s][t]>'#'!=A[E]-A[a*C+b]-B[s*C+t]+d-Y-abs(b-t)>99for t in U(max(b-d,1),min(b+d+1,C)))][1]for s in U(max(a-Y,1),min(a+Y+1,R)))for a in U(R)for b in U(C)if'#'',((0,-1),(1,0),(-1,0),(0,1))));A={a+b:'><'[l(b:=F[3*k+l])};f=lru_cache(lambda s,n:n<2and len(s)or sum(min(f(''.join(p)+'A',(n-2)|1)for p in permutations(A[s[i-1]+s[i]])if[r:=(t:=divmod((u:=(N,D)[n%2]).index(s[i-1]),3))[0],c:=t[1],all(4-n%2*2>(r:=r+K[q][0])>-1<(c:=c+K[q][1])<3!=u[3*r+c]<'x'for q in p)][2])for i in U(len(s))));Z=[0,0];[Z.__setitem__(p,Z[p]+f(s.strip(),6+46*p)*int(''.join(x for x in s if'/'>5&M^x,x:=x<<11&M^x,P:=(20*P+p-(p:=x%10))%20**4,i>2and R.setdefault(P,p)]for i in range(2000)],x,[X.__setitem__(i,X[i]+R[i])for i in R]][5]for u in map(int,open(0))),'\nPart 2:',max(X)) 45 | # Day 23: 317 46 | S=set;g={};F=g.setdefault;[F(a:=r[:2],S()).add(b:=r[3:5])!=F(b,S()).add(a)for r in open(0)];f=lambda r,p,x:p|x and max((f(r|{w},p&g[w],x&g[w])for w in p-g[min(p|x)]),key=len)or','.join(sorted(r));print('Part 1:',len({u for i in g for j in g[i]for k in g[i]&g[j]if't'in(u:=i+j+k)[::2]})//6,'\nPart 2:',f(S(),{*g},S())) 47 | # Day 24: 773 48 | e='XOR';q='AND';N='\n';P={e:'^','OR':'|',q:'&'};s,t=open(0).read().split(N*2);Z=t.count('z');T={[u:=x.split(),tuple(u[:3])][1]:u[4]for x in t.split(N)};F=lambda a,b,c:max([k for k in T if k in((a,c,b),(b,c,a))]+[()]);M={i[:3]:i[4:]for i in s.split(N)};S=C=[];[a in M and c in M and M.update({T[(a,b,c)]:eval(f'{M[a]}{P[b]}{M[c]}')})for _ in T for a,b,c in T];T[()]='a';W=lambda a,b:T.update({a:T[b],b:T[a]})!=S.extend((T[a],T[b]));[[z:=(),c:=(),v:=(f'x{i:02}',f'y{i:02}'),m:=F(*v,e),n:=F(*v,q),C and[r:=F(T[C],T[m],q)or W(m,n)or F(T[C],T[m],q),z:=F(T[C],T[m],e),[T[x][0]>'y'!=W(x,z)for x in(m,n,r)],c:=F(T[r],T[n],'OR')],'z'=h['b'])*(h['r']<13),h['b']*h['g']*h['r'])][3]for l in __import__('sys').stdin),print('Part 1:',z(u.real),'\nPart 2:',z(u.imag))] 5 | # Day 03: 525 6 | [r:=range,m:=[*map(str.strip,__import__('sys').stdin)],R:=len(m),C:=len(m[0]),q:=0,x:=r(-1,2),A:=set(),[[n:=set(),[[k:=v,[[k:=k-(k+1and'/'(u:=i+s)>=0and C>(v:=j+t)>=0and'/'0)//2for s in c),'\nPart 2:',sum(d))] 9 | # Day 05: 698 10 | [S:=str.split,A:=list.append,I:=__import__('sys').stdin.readline,c:=lambda s:[x:=[],[[u:=[],[[A(x,(max(a+p-q,p),min(b+p-q,p+r-1))),A(u,(max(a,q),min(b,q+r-1)))]for p,q,r in d if(a=q)],0if u else[A(x,(a,b)),A(u,x[-1])],A(x,(a,u[0][0]-1)),u.insert(0,x[-1]),A(x,(u[-1][1]+1,b)),A(u,x[-1]),[A(x,(e[1]+1,f[0]-1))for e,f in zip(u,u[1:])]]for a,b in s],[(a,b)for a,b in x if a<=b]][2],s:=[s:=[*map(lambda x:[int(x)]*2,S(S(I(),':')[1]))],[[t:=s[2*i][0],t+s[2*i+1][0]-1]for i in range(len(s)//2)]],I(),[[I(),d:=[1],[(A(d,[*map(int,S(I()))])if not d or d[-1]else 0)for i in d],d:=d[1:-1],d.sort(key=lambda x:x[1]),s:=[*map(c,s)]]for _ in'.'*7],print('Part 1:',min(s[0])[0],'\nPart 2:',min(s[1])[0])] 11 | # Day 06: 185 12 | [f:=1,l:=[input().split()[1:]for _ in'..'],g:=lambda a,b:a-1-2*int((a-(a*a-4*b)**.5)/2),[f:=f*g(*map(int,i))for i in zip(*l)],print('Part 1:',f,'\nPart 2:',g(*map(int,map(''.join,l))))] 13 | # Day 07: 349 14 | [m:=dict(zip('TJQKA',':;<=>')),d:=[*map(str.split,(I:=__import__)('sys').stdin)],s:=lambda t:sum((i+1)*int(e[1])for i,e in enumerate(sorted(d,key=lambda c:max((lambda f:[max(f),-len(f)])(I('collections').Counter(c[0].replace(t,i)).values())for i in c[0])+[m.get(i,i)for i in c[0]]))),print('Part 1:',s('@')),m:={**m,'J':'1'},print('Part 2:',s('J'))] 15 | # Day 08: 328 16 | [I:=__import__,m:=input().strip(),input(),g:=dict(((n:=I('re').findall('\w+',l))[0],n[1:])for l in I('sys').stdin),d:=lambda p,s:[[p:=g[p][i>'L']for i in m],len(m)+(0if'Z'*s==p[3-s:]else d(p,s))][1],print('Part 1:',d('AAA',3),'\nPart 2:',I('functools').reduce(lambda x,y:x*y//I('math').gcd(x,y),[d(i,1)for i in g if'A'==i[2]]))] 17 | # Day 09: 197 18 | print('Part 1:',sum((M:=map)(E:=lambda l:l[-1]+E([b-a for a,b in zip(l,l[1:])])if l else 0,L:=[*M(lambda x:[*M(int,x.split())],__import__('sys').stdin)])),'\nPart 2:',sum(M(lambda x:E(x[::-1]),L))) 19 | # Day 10: 792 20 | [x:=range,b:=[*map(str.strip,__import__('sys').stdin)],m:=[[A:='@']*(C:=2*len(b[0])+1)],[m.extend([[*(A+A.join(l)+A)],m[0]])for l in b],R:=len(m),Z:=x(X:=R*C),d:=[-2]*X,S:=d.__setitem__,g:=[[]for _ in Z],q:=[(u,0)for u in Z if'S'==m[u//C][u%C]],s:=[(0,0)],f:=lambda a,b:(g[a].append(b),g[b].append(a)),[[t:=m[u//C][u%C],f(u,u-C)if t in'S|LJ'else 0,f(u,u+C)if t in'S|7F'else 0,f(u,u+1)if t in'S-LF'else 0,f(u,u-1)if t in'S-J7'else 0]for u in Z],[[t:=q[0][1],u:=q.pop(0)[0],[S(u,t),q.extend((v,t+1)for v in g[u])]if d[u]<0else 0]for _ in x(X*4)if q],[[r:=s[-1][0],c:=s.pop()[1],[S(C*r+c,0),s.extend((r+p,c+z)for p,z in((0,-1),(0,1),(-1,0),(1,0))if R>r+p>-1d[C*r+c]else 0]for _ in x(X*4)if s],print('Part 1:',max(d)//2,'\nPart 2:',sum(0>d[C*r+c]for r in x(1,R,2)for c in x(1,C,2)))] 21 | # Day 11: 398 22 | [A:=list.append,m:=[*map(str.strip,__import__('sys').stdin)],x:=range,f:=lambda e:[p:=[0],q:=[0],G:=[],r:={*x(R:=len(m))},c:={*x(C:=len(m[0]))},[[r:=r-{i},c:=c-{j},A(G,(i+1,j+1))]for i in x(R)for j in x(C)if'.'>m[i][j]],[A(l,l[i]+1+e*(i in h))for l,h,H in((p,r,R),(q,c,C))for i in x(H)],sum(abs(p[a]-p[c])+abs(q[b]-q[d])for a,b in G for c,d in G)//2][7],print('Part 1:',f(1),'\nPart 2:',f(999999))] 23 | # Day 12: 467 24 | [L:=len,g:=lambda l,p:[m:={},f:=lambda i,j,c:m[t]if(t:=(i,j,c))in m else(c==p[-1])*(L(p)-1==j)|(c<1)*(j==L(p))if i==L(l)else[r:=(f(i+1,j,c+1)if l[i]in'?#'else 0)+(f(i+1,j,0)if(k:=l[i]in'?.')*(c<1)else 0)+(f(i+1,j+1,0)if k*c*(jj>-1b>-1',int(c[2:]),j[1])][2]for v in u[:-1]]+[u[-1]]][1]for l in m[:k]},f:=lambda h,c='in':I('math').prod(b-a+1for a,b in h)*(c<'B')if c<'Z'else sum([a:=h[v][0],b:=h[v][1],A:=h[:v],B:=h[v+1:],S:=h.__setitem__,[S(v,(x:=min(z,b+1),b)),f(A+[(a,x-1)]+B,w)][1]if s*(z>a)else[S(v,(a,x:=max(a-1,z))),f(A+[(x+1,b)]+B,w)][1]if(1-s)*(z1e3else(z[0]+1-p,z[1]+p),u in T and[n:=-1,[(n:=p)if T[u]==2else(U(R[u],Z[2],p),n:=1-all(V(R[u])))if T[u]else U(S,u,n:=1^S[u])if p^1else 0],n<0 or q.extend((v,n,u)for v in G[u]),u==K and[U(H,k,t)for k in R[u]if(k not in H)*R[u][k]]])for Z in q],D.append(0)]for i in D],print('Part 1:',z[0]*z[1],'\nPart 2:',I('functools').reduce(lambda x,y:x*y//I('math').gcd(x,y),V(H)))] 41 | # Day 21: 397 42 | [R:=len(m:=[*__import__('sys').stdin]),H:=[1],T:=(0,1),p:={R//2*(1+1j)},q:=set(),s:={T},[([(s.add(v),[(w:=v+x,m[int(w.real)%R][int(w.imag)%R]<'.'or w in s or q.add(w))for x in(-1j,1j,1,-1)])for v in p],T:=[T[1],T[0]+len(p:=q)],q:=set(),H:=H+T[1:])for _ in'.'*3*R],f:=lambda n:[v:=H[n%R::R],n:=n//R,a:=v[0],a+n*(v[1]-a)+n*(n-1)//2*(v[2]-2*v[1]+a)][3],print('Part 1:',f(64),'\nPart 2:',f(26501365))] 43 | # Day 22: 689 44 | [X:=range,U:=list.__setitem__,P:=__import__,L:=lambda a,c,e,b,d,f:P('itertools').product(X(a,b+1),X(c,d+1),X(e,f+1)),B:={},N:=X(M:=len(S:=sorted([[*map(int,P('re').findall('\d+',l))]for l in P('sys').stdin],key=lambda x:x[2]))),I:=[0]*M,C:=lambda i,d=-1:[J:=[*I],s:=[i],[(d:=d+1,[U(J,v,J[v]-1)or J[v]or s.append(v)for v in G[u]])for u in s],d][3],[[j:=S[i]]+[(U(j,2,j[2]-1),U(j,5,j[5]-1),any(i-B.get(t,i)for t in L(*j))and[U(j,k,j[k]+1)for k in(2,5)])for _ in X(j[2])]+[B:={**B,t:i}for t in L(*j)]for i in N],G:=[(s:={B[j]for*a,z in L(*S[i])if i-B.get(j:=(*a,z+1),i)},[U(I,j,I[j]+1)for j in s])[0]for i in N],print('Part 1:',sum(all(I[j]-1for j in v)for v in G),'\nPart 2:',sum(map(C,N)))] 45 | # Day 23: 742 46 | [R:=len(m:=[*map(str.strip,__import__('sys').stdin)]),C:=len(m[0]),X:=range(R*C),S:=dict.__setitem__,F:=[{}for _ in X],G:={i:{}for i in X},[(r:=e//C,c:=e%C,m[r][c]>'#'and[R>r+i>-1'.')and S(F[e],n,1),S(G[e],n,1))for i,j,z in((0,-1,'<'),(0,1,'>'),(1,0,'v'),(-1,0,'^'))])for e in X],[(k:=[*G[u]],l:=sum(G[u].values()),a:=k[0],b:=k[1],S(G,u,{}),G[a].pop(u),G[b].pop(u),S(G[a],b,l),S(G[b],a,l))for u in X if len(G[u])==2],f:=lambda g,p={0},a=0:[s:=[(1,0,0)],[(x:=s.pop(),v:=x[0],d:=x[2],p.remove(v)if x[1]else(v in p)or((a:=max(a,d))if v==R*C-2else(p.add(v),s.append((v,1,d)),s.extend((w,0,d+g[v][w])for w in g[v]))))[0]for _ in iter(lambda:s,[])],a][2],print('Part 1:',f(F),'\nPart 2:',f(G))] 47 | # Day 24: 818 48 | [I:=__import__,N:=len(D:=[[*map(int,I('re').findall('[-\d]+',l))]for l in I('sys').stdin]),r:=0,A:=[],X:=range,V:=list.__setitem__,[(T:=D[i],u:=T[0],v:=T[1],x:=T[3],y:=T[4],S:=D[j],k:=S[0],l:=S[1],n:=S[3],o:=S[4],(q:=n*y-x*o)and(t:=((u-k)*o+n*(l-v))/q,r:=r+(t>0<(x*t+u-k)/n)*(2e14<=u+x*t<=4e14>=v+y*t>=2e14)),A.extend(([y-o,n-x,0,l-v,u-k,0,u*y+l*n-v*x-k*o],[T[5]-S[5],0,n-x,S[2]-T[2],0,u-k,u*T[5]+S[2]*n-T[2]*x-k*S[5]])),A:=A[:6])for i in X(N)for j in X(i+1,N)],A:=[[*map(I('fractions').Fraction,a)]for a in A[:6]],F:=lambda i,j,c:[V(A[i],k,A[i][k]-c*A[j][k])for k in X(7)],[(C:=lambda e:e if A[e][R]else C(e+1),f:=C(R),g:=A[f],V(A,f,A[R]),V(A,R,[j/g[R]for j in g]),[F(i,R,A[i][R])for i in X(R+1,6)])for R in X(6)],[F(j,5-i,A[j][5-i])for i in X(5)for j in X(5-i)],print('Part 1:',r,'\nPart 2:',sum([*zip(*A)][6][:3]))] 49 | # Day 25: 959 50 | [I:=__import__,g:={},r:={},X:=range,L:=len,S:=list.__setitem__,Q:=list.append,[(t:=I('re').findall('\w+',l),a:=t[0],r:={**r,a:r.get(a,L(r))},g:={**g,a:t[1:]},[r:={**r,v:r.get(v,L(r))}for v in g[a]])for l in I('sys').stdin],V:=L(r),E:=[],A:=[[]for _ in X(V)],[(Q(E,[r[j],0]),Q(A[r[i]],L(E)-1),Q(E,[r[i],0]),Q(A[r[j]],L(E)-1))for i in g for j in g[i]],B:=lambda s,t,o=1:(S(d,s,0),q:=[s],[k:=([(w:=E[i],v:=w[0],d[v]-1))for u in q],L(k)==2and k[1])[3],D:=lambda u,t,f=9,o=0:[[(S(P,u,i),w:=E[A[u][i]],o<1and d[w[0]]==d[u]+1and(p:=D(w[0],t,min(f,1-w[1])))and(S(w,1,w[1]+p),S(T:=E[A[u][i]^1],1,T[1]-p),o:=p)[2])for i in X(P[u],L(A[u]))],o][1]if(u-t)*f else f,[(m:=0,d:=[-1]*V,[S(e,1,0)for e in E],W:=[0],[B(s,t)and(Q(W,0),P:=[0]*V,[m:=m+D(s,t)for _ in A],d:=[-1]*V)for _ in W],m-3or(c:=sum(i>-1 for i in d),print('Part 1:',c*(V-c),'\nPart 2: THE END!'),exit(0)))for s in X(V)for t in X(s+1,V)]] --------------------------------------------------------------------------------