Compare commits
10 Commits
1d4c5f6f81
...
main
Author | SHA1 | Date | |
---|---|---|---|
e58ddb9f96 | |||
d165384617 | |||
6fe70f851f | |||
a4e02c42a7 | |||
032f0c4caa | |||
a59c3c697c | |||
6be1a222b1 | |||
a6c027a1af | |||
3142bc1ebb | |||
95665139a7 |
56
d07/part1.py
Normal file
56
d07/part1.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import sys
|
||||||
|
from collections import Counter as C
|
||||||
|
from functools import cmp_to_key as ctk
|
||||||
|
|
||||||
|
def score(h:str) -> int: # get type of a hand
|
||||||
|
D = C(h)
|
||||||
|
E = C(v for k,v in D.items())
|
||||||
|
if 5 in E: # five of a kind
|
||||||
|
return 7
|
||||||
|
elif 4 in E: # four of a kind
|
||||||
|
return 6
|
||||||
|
elif 3 in E and 2 in E: # full house
|
||||||
|
return 5
|
||||||
|
elif 3 in E: # three of a kind
|
||||||
|
return 4
|
||||||
|
elif 2 in E and E[2] == 2: # two pairs
|
||||||
|
return 3
|
||||||
|
elif 2 in E:
|
||||||
|
return 2
|
||||||
|
else: # high card
|
||||||
|
return 1
|
||||||
|
|
||||||
|
H = list(reversed('AKQJT98765432'))
|
||||||
|
|
||||||
|
def compareH(h1, h2):
|
||||||
|
for a,b in zip(h1,h2):
|
||||||
|
if H.index(a) < H.index(b):
|
||||||
|
return 1
|
||||||
|
elif H.index(a) > H.index(b):
|
||||||
|
return -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def compare(T1, T2): # return >:-1, ==:0, <:1
|
||||||
|
h1, s1, *_ = T1
|
||||||
|
h2, s2, *_ = T2
|
||||||
|
s1 = score(h1)
|
||||||
|
s2 = score(h2)
|
||||||
|
if s1 < s2:
|
||||||
|
return 1
|
||||||
|
elif s2 < s1:
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
return compareH(h1,h2)
|
||||||
|
|
||||||
|
L = [ l.split() for l in sys.stdin.read().splitlines()]
|
||||||
|
L = [[h,int(b)] for [h,b] in L]
|
||||||
|
|
||||||
|
for h,b in L:
|
||||||
|
print(h, score(h))
|
||||||
|
pass
|
||||||
|
|
||||||
|
L.sort(key=ctk(compare))
|
||||||
|
|
||||||
|
print(
|
||||||
|
sum((i+1)*b for i,(h,b) in enumerate(reversed(L)))
|
||||||
|
)
|
42
d07/part2.py
Normal file
42
d07/part2.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import sys
|
||||||
|
from collections import Counter as C
|
||||||
|
from functools import cmp_to_key as ctk
|
||||||
|
|
||||||
|
H = list(reversed('AKQT98765432J'))
|
||||||
|
|
||||||
|
def score(h:str) -> int:
|
||||||
|
D = C(h)
|
||||||
|
j = D['J']
|
||||||
|
del D['J']
|
||||||
|
if j<5:
|
||||||
|
m = max(D.values())
|
||||||
|
for k,v in D.items():
|
||||||
|
if v == m:
|
||||||
|
D[k] = v+j
|
||||||
|
break
|
||||||
|
E = C(v for k,v in D.items()) if j<5 else {5:1}
|
||||||
|
r = 0
|
||||||
|
if 5 in E: # five of a kind
|
||||||
|
r = 7
|
||||||
|
elif 4 in E: # four of a kind
|
||||||
|
r = 6
|
||||||
|
elif 3 in E and 2 in E: # full house
|
||||||
|
r = 5
|
||||||
|
elif 3 in E: # three of a kind
|
||||||
|
r = 4
|
||||||
|
elif 2 in E and E[2] == 2: # two pairs
|
||||||
|
r = 3
|
||||||
|
elif 2 in E: # one pair
|
||||||
|
r = 2
|
||||||
|
else: # high card
|
||||||
|
r = 1
|
||||||
|
return (r, *[H.index(c) for c in h])
|
||||||
|
|
||||||
|
L = [ l.split() for l in sys.stdin.read().splitlines()]
|
||||||
|
L = [(score(h),int(b)) for [h,b] in L]
|
||||||
|
|
||||||
|
sorted(L)
|
||||||
|
|
||||||
|
print(
|
||||||
|
sum((i+1)*b for i,(h,b) in enumerate(reversed(L)))
|
||||||
|
)
|
18
d07/terse.py
Normal file
18
d07/terse.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from collections import Counter
|
||||||
|
lines = [i for i in open('input').read().split('\n') if i.strip()]
|
||||||
|
def hand(h,part1):
|
||||||
|
if part1: h = h.replace('J', 'X')
|
||||||
|
h2 = ['J23456789TXQKA'.index(i)for i in h]
|
||||||
|
ts = []
|
||||||
|
for r in '23456789TQKA':
|
||||||
|
c = Counter(h.replace('J', r))
|
||||||
|
p = tuple(sorted(c.values()))
|
||||||
|
t = [(1,1,1,1,1),(1,1,1,2),(1,2,2),(1,1,3),(2,3),(1,4),(5,)].index(p)
|
||||||
|
ts.append(t)
|
||||||
|
return (max(ts), *h2)
|
||||||
|
for part1 in (True, False):
|
||||||
|
h = sorted((hand(h,part1), int(b)) for h, b in (l.split() for l in lines))
|
||||||
|
t = 0
|
||||||
|
for i,(_,b) in enumerate(h):
|
||||||
|
t+=i*b+b
|
||||||
|
print('Part', 2-part1, ':', t)
|
22
d08/run.py
Normal file
22
d08/run.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import sys
|
||||||
|
from itertools import cycle
|
||||||
|
from math import lcm
|
||||||
|
|
||||||
|
I, _, *P = [l for l in sys.stdin.read().splitlines()]
|
||||||
|
# 0000000000111111111
|
||||||
|
# 0123456789012345678
|
||||||
|
# BCN = (HFN, KFC)
|
||||||
|
P = {l[0:3]:(l[7:10],l[12:15]) for l in P}
|
||||||
|
|
||||||
|
def countsteps(g):
|
||||||
|
C = g
|
||||||
|
N = 0
|
||||||
|
for i in cycle(I):
|
||||||
|
if C[2] == 'Z':
|
||||||
|
break
|
||||||
|
C = P[C][i == 'R']
|
||||||
|
N += 1
|
||||||
|
return N
|
||||||
|
|
||||||
|
print("part 1:", countsteps("AAA"))
|
||||||
|
print("part 2:", lcm(*(countsteps(p) for p in P.keys() if p[2] == 'A')))
|
11
d09/part1.py
11
d09/part1.py
@@ -1,11 +0,0 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
L = [list(map(int,l.split(' '))) for l in sys.stdin.read().splitlines()]
|
|
||||||
|
|
||||||
def extrapolate(L):
|
|
||||||
if all(not a for a in L):
|
|
||||||
return L+[0]
|
|
||||||
M = [b-a for a,b in zip(L,L[1:])]
|
|
||||||
return L+[L[-1]+extrapolate(M)[-1]]
|
|
||||||
|
|
||||||
print(sum(extrapolate(l)[-1] for l in L))
|
|
11
d09/part2.py
11
d09/part2.py
@@ -1,11 +0,0 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
L = [list(map(int,l.split(' '))) for l in sys.stdin.read().splitlines()]
|
|
||||||
|
|
||||||
def extrapolate(L):
|
|
||||||
if all(not a for a in L):
|
|
||||||
return [0]+L
|
|
||||||
M = [b-a for a,b in zip(L,L[1:])]
|
|
||||||
return [L[0]-extrapolate(M)[0]]+L
|
|
||||||
|
|
||||||
print(sum(extrapolate(l)[0] for l in L))
|
|
12
d09/run.py
Normal file
12
d09/run.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
L = [list(map(int,l.split(' '))) for l in sys.stdin.read().splitlines()]
|
||||||
|
|
||||||
|
def extrapolate(L):
|
||||||
|
if all(a == 0 for a in L):
|
||||||
|
return 0
|
||||||
|
M = [b-a for a,b in zip(L,L[1:])]
|
||||||
|
return L[-1]+extrapolate(M)
|
||||||
|
|
||||||
|
print(sum(extrapolate(l) for l in L))
|
||||||
|
print(sum(extrapolate(l[::-1]) for l in L))
|
59
d10/run.py
Normal file
59
d10/run.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
# parse
|
||||||
|
I = sys.stdin.read().splitlines()
|
||||||
|
G = [list(l) for l in I]
|
||||||
|
W = len(G[0])
|
||||||
|
H = len(G)
|
||||||
|
|
||||||
|
# look for S
|
||||||
|
S = None
|
||||||
|
for y in range(H):
|
||||||
|
if (x := I[y].find("S")) > -1:
|
||||||
|
S = (x,y)
|
||||||
|
break
|
||||||
|
|
||||||
|
# encode moves
|
||||||
|
D = {
|
||||||
|
'u': {'|': ( 0,-1,'u'), 'F': ( 1, 0,'r'), '7': (-1, 0,'l')},
|
||||||
|
'r': {'-': ( 1, 0,'r'), 'J': ( 0,-1,'u'), '7': ( 0, 1,'d')},
|
||||||
|
'd': {'|': ( 0, 1,'d'), 'L': ( 1, 0,'r'), 'J': (-1, 0,'l')},
|
||||||
|
'l': {'-': (-1, 0,'l'), 'L': ( 0,-1,'u'), 'F': ( 0, 1,'d')},
|
||||||
|
}
|
||||||
|
|
||||||
|
# part 1
|
||||||
|
poly = [S] # vertices of the polygone
|
||||||
|
x0, y0 = S
|
||||||
|
P = (x0+1, y0, 'r') # start at S and go right
|
||||||
|
for _ in range(100_000):
|
||||||
|
x, y, d = P
|
||||||
|
poly.append((x,y))
|
||||||
|
z = G[y][x]
|
||||||
|
if z == 'S':
|
||||||
|
break
|
||||||
|
dx,dy,nd = D[d].get(z)
|
||||||
|
P = (x+dx,y+dy,nd)
|
||||||
|
print(len(poly)//2)
|
||||||
|
|
||||||
|
# part 2
|
||||||
|
from matplotlib.path import Path
|
||||||
|
|
||||||
|
pg = Path(poly)
|
||||||
|
|
||||||
|
J = [['.']*W for _ in range(H)]
|
||||||
|
R = 0
|
||||||
|
for y in range(W):
|
||||||
|
for x in range(H):
|
||||||
|
if (x,y) in poly:
|
||||||
|
J[y][x] = G[y][x]
|
||||||
|
elif pg.contains_point((x,y)):
|
||||||
|
R += 1
|
||||||
|
J[y][x] = "O"
|
||||||
|
print(R)
|
||||||
|
|
||||||
|
# plot
|
||||||
|
J[y0][x0] = "S"
|
||||||
|
T = str.maketrans("|-LJ7F", "│─└┘┐┌")
|
||||||
|
with open("grid.txt","wt") as f:
|
||||||
|
for row in J:
|
||||||
|
print("".join(row).translate(T), file=f)
|
27
d11/run.py
Normal file
27
d11/run.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import sys
|
||||||
|
from itertools import combinations as Comb
|
||||||
|
|
||||||
|
I = sys.stdin.read().splitlines() # for codon type inference
|
||||||
|
L = [list(l) for l in I]
|
||||||
|
H = len(L)
|
||||||
|
W = len(L[0])
|
||||||
|
|
||||||
|
RD = [y for y in range(W) if all(L[y][x] == '.' for x in range(H))]
|
||||||
|
CD = [x for x in range(H) if all(L[y][x] == '.' for y in range(W))]
|
||||||
|
G = [(x,y) for y in range(W) for x in range(H) if L[y][x] == '#']
|
||||||
|
|
||||||
|
# expantion factor, 2 for part 1, 1E6 for part 2
|
||||||
|
X = int(float(sys.argv[1])) # float to parse scientific form, int for codon
|
||||||
|
|
||||||
|
def exp(a:int, b:int, S:list[int]) -> int:
|
||||||
|
if a > b:
|
||||||
|
b, a = a, b
|
||||||
|
return sum(1 for s in S if a<s<b)
|
||||||
|
|
||||||
|
S = 0
|
||||||
|
for (x1,y1),(x2,y2) in Comb(G,2):
|
||||||
|
ex = exp(x1, x2, CD)
|
||||||
|
ey = exp(y1, y2, RD)
|
||||||
|
d = abs(x2-x1) + abs(y2-y1) + (X-1)*(ex+ey)
|
||||||
|
S += d
|
||||||
|
print(int(S))
|
40
d12/part1.block.py
Normal file
40
d12/part1.block.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
def strset(s,i,c):
|
||||||
|
return s[:i]+c+s[i+1:]
|
||||||
|
|
||||||
|
def next(pat, nums, patc=''): # pat must terminiate with '.'
|
||||||
|
#print(f"next {pat=} {nums=} ({patc=}), {len(pat)+len(patc)}")
|
||||||
|
if len(nums) == 0:
|
||||||
|
if pat.find('#')<0:
|
||||||
|
#print("valid", patc)
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
# find all ways to build first block
|
||||||
|
l = nums[0]
|
||||||
|
block = '#'*l
|
||||||
|
rest = sum(nums[1:])
|
||||||
|
n = 0
|
||||||
|
m = len(pat)-l-rest
|
||||||
|
for i in range(m):
|
||||||
|
# if can build block:
|
||||||
|
z = pat[i:i+l].replace('?','#')
|
||||||
|
#print(f"{i=}/{m=} {z=}, {pat[i+l]}")
|
||||||
|
if z == block:
|
||||||
|
##print("march, and ", pat[i+l])
|
||||||
|
if pat[:i].find('#')<0 and not pat[i+l] == '#': # '.' or '?'
|
||||||
|
#pat = strset(pat, i+l, '.')
|
||||||
|
# recurse
|
||||||
|
r = next(pat[i+l+1:], nums[1:], patc+pat[:i].replace('?','.')+z+'.')
|
||||||
|
if r > 0:
|
||||||
|
n += r
|
||||||
|
return n
|
||||||
|
|
||||||
|
S= 0
|
||||||
|
for i,l in enumerate(sys.stdin.read().splitlines()):
|
||||||
|
pattern, snums = l.split(' ')
|
||||||
|
nums = list(map(int,snums.split(',')))
|
||||||
|
n = next(pattern+'.', nums)
|
||||||
|
print(i,l,n)
|
||||||
|
S += n
|
||||||
|
print(S)
|
37
d12/part1.len.py
Normal file
37
d12/part1.len.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
def valid(pat:str, nums:list[int]):
|
||||||
|
pat += '.'
|
||||||
|
c = 0
|
||||||
|
for i,p in enumerate(pat):
|
||||||
|
if p == '#':
|
||||||
|
c += 1
|
||||||
|
else:
|
||||||
|
if c>0:
|
||||||
|
if c == nums[0]:
|
||||||
|
c = 0
|
||||||
|
nums = nums[1:]
|
||||||
|
if len(nums) == 0:
|
||||||
|
return 1 if pat[i:].find('#')<0 else 0
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def next(pattern, nums):
|
||||||
|
i = pattern.find('?')
|
||||||
|
if i < 0:
|
||||||
|
v = valid(pattern, nums)
|
||||||
|
if v == 1:
|
||||||
|
print("valid", pattern)
|
||||||
|
return v
|
||||||
|
else:
|
||||||
|
return next(pattern[:i]+'.'+pattern[i+1:], nums)+next(pattern[:i]+'#'+pattern[i+1:], nums)
|
||||||
|
|
||||||
|
S= 0
|
||||||
|
for i,l in enumerate(sys.stdin.read().splitlines()):
|
||||||
|
pattern, snums = l.split(' ')
|
||||||
|
nums = list(map(int,snums.split(',')))
|
||||||
|
n = next(pattern, nums)
|
||||||
|
print(i,l,n)
|
||||||
|
S += n
|
||||||
|
print(S)
|
31
d12/part1.list.py
Normal file
31
d12/part1.list.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
def valid(pattern, nums):
|
||||||
|
l = []
|
||||||
|
c = ''
|
||||||
|
for p in pattern:
|
||||||
|
if p == '#':
|
||||||
|
c+=p
|
||||||
|
else:
|
||||||
|
if len(c):
|
||||||
|
l.append(c)
|
||||||
|
c = ''
|
||||||
|
if len(c):
|
||||||
|
l.append(c)
|
||||||
|
c = ''
|
||||||
|
l = [len(m) for m in l]
|
||||||
|
return 1 if l == nums else 0
|
||||||
|
|
||||||
|
def next(pattern, nums):
|
||||||
|
i = pattern.find('?')
|
||||||
|
if i < 0:
|
||||||
|
return valid(pattern, nums)
|
||||||
|
else:
|
||||||
|
return next(pattern[:i]+'.'+pattern[i+1:], nums)+next(pattern[:i]+'#'+pattern[i+1:], nums)
|
||||||
|
|
||||||
|
S= 0
|
||||||
|
for l in sys.stdin.read().splitlines():
|
||||||
|
pattern, snums = l.split(' ')
|
||||||
|
nums = list(map(int,snums.split(',')))
|
||||||
|
S += next(pattern, nums)
|
||||||
|
print(S)
|
49
d14/run.py
Normal file
49
d14/run.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
I = sys.stdin.read().splitlines()
|
||||||
|
G = [list(l) for l in I]
|
||||||
|
R = len(G)
|
||||||
|
C = len(G[0])
|
||||||
|
|
||||||
|
def rotate(G, F):
|
||||||
|
for r in range(R):
|
||||||
|
for c in range(C):
|
||||||
|
F[c][R-1-r] = G[r][c]
|
||||||
|
|
||||||
|
def tilt(G):
|
||||||
|
for x in range(C):
|
||||||
|
for y in range(R):
|
||||||
|
if G[y][x] == "O":
|
||||||
|
for j in range(y-1,0-1,-1):
|
||||||
|
if G[j][x] == '.':
|
||||||
|
G[j][x] = "O"
|
||||||
|
G[j+1][x] = "."
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
score = lambda: sum((R-y)*row.count('O') for y,row in enumerate(G))
|
||||||
|
|
||||||
|
cache = {}
|
||||||
|
F = [['?' for _ in range(C)] for _ in range(R)] # pre-allocate saves 10% time (no GC)
|
||||||
|
|
||||||
|
target = 1_000_000_000
|
||||||
|
t = 0
|
||||||
|
while t<target:
|
||||||
|
print(t, end='\r')
|
||||||
|
t += 1
|
||||||
|
for j in range(4):
|
||||||
|
tilt(G)
|
||||||
|
if t==1 and j==0: # part 1
|
||||||
|
print(score())
|
||||||
|
rotate(G, F); F, G = G, F
|
||||||
|
#Gh = tuple(tuple(row) for row in G)
|
||||||
|
Gh = ''.join(''.join(row) for row in G)
|
||||||
|
if Gh in cache:
|
||||||
|
cycle_length = t-cache[Gh]
|
||||||
|
print(f'{t=}, {cycle_length=}')
|
||||||
|
amt = (target-t)//cycle_length
|
||||||
|
t += amt * cycle_length
|
||||||
|
cache[Gh] = t
|
||||||
|
|
||||||
|
print(t, score())
|
||||||
|
|
30
d15/run.py
Normal file
30
d15/run.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
def hash(l):
|
||||||
|
c = 0
|
||||||
|
for w in l:
|
||||||
|
c += ord(w)
|
||||||
|
c *= 17
|
||||||
|
c = c % 256
|
||||||
|
return c
|
||||||
|
|
||||||
|
L = sys.stdin.read().split(',')
|
||||||
|
|
||||||
|
print(sum(hash(l) for l in L))
|
||||||
|
|
||||||
|
B = [ dict() for _ in range(256) ]
|
||||||
|
|
||||||
|
for l in L:
|
||||||
|
e = l.find('=')
|
||||||
|
d = l.find('-')
|
||||||
|
i = max(e,d)
|
||||||
|
lbl = l[:i]
|
||||||
|
box = hash(lbl)
|
||||||
|
if e > 0: # set
|
||||||
|
v = int(l[i+1:])
|
||||||
|
B[box][lbl] = v
|
||||||
|
elif d > 0: # remove
|
||||||
|
if lbl in B[box]:
|
||||||
|
del B[box][lbl]
|
||||||
|
|
||||||
|
print(sum((i+1)*(j+1)*v for i, b in enumerate(B) for j,(k,v) in enumerate(b.items())))
|
Reference in New Issue
Block a user