Compare commits
2 Commits
8c27fca769
...
38923eb7a7
Author | SHA1 | Date |
---|---|---|
Tibor Bizjak | 38923eb7a7 | |
Tibor Bizjak | 072bf8409d |
12
day03.py
12
day03.py
|
@ -1,5 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from functools import cache
|
||||||
|
|
||||||
up = lambda v: (v[0], v[1] + 1)
|
up = lambda v: (v[0], v[1] + 1)
|
||||||
down = lambda v: (v[0], v[1] - 1)
|
down = lambda v: (v[0], v[1] - 1)
|
||||||
left = lambda v: (v[0] - 1, v[1])
|
left = lambda v: (v[0] - 1, v[1])
|
||||||
|
@ -11,20 +13,12 @@ moves = {'U' : up,
|
||||||
'R' : right
|
'R' : right
|
||||||
}
|
}
|
||||||
|
|
||||||
def memoize(f):
|
|
||||||
cache = dict()
|
|
||||||
def memf(path):
|
|
||||||
if path not in cache:
|
|
||||||
cache[path] = f(path)
|
|
||||||
return cache[path]
|
|
||||||
return memf
|
|
||||||
|
|
||||||
def iterate(f, x, N):
|
def iterate(f, x, N):
|
||||||
for i in range(N):
|
for i in range(N):
|
||||||
yield x
|
yield x
|
||||||
x = f(x)
|
x = f(x)
|
||||||
|
|
||||||
@memoize
|
@cache
|
||||||
def lines(path):
|
def lines(path):
|
||||||
pos = (0, 0)
|
pos = (0, 0)
|
||||||
r = []
|
r = []
|
||||||
|
|
5
day07.py
5
day07.py
|
@ -2,14 +2,15 @@
|
||||||
|
|
||||||
from intcode import preproc
|
from intcode import preproc
|
||||||
from itertools import permutations
|
from itertools import permutations
|
||||||
from lib import memoize, last
|
from lib import last
|
||||||
|
from functools import cache
|
||||||
|
|
||||||
stack_size = 5
|
stack_size = 5
|
||||||
fst_amp_input = 0
|
fst_amp_input = 0
|
||||||
|
|
||||||
|
|
||||||
def partI(amp):
|
def partI(amp):
|
||||||
run_amp = memoize(lambda *args : last(amp(*args)))
|
run_amp = cache(lambda *args : last(amp(*args)))
|
||||||
|
|
||||||
phase_range = range(stack_size)
|
phase_range = range(stack_size)
|
||||||
best = 0
|
best = 0
|
||||||
|
|
13
day08.py
13
day08.py
|
@ -1,14 +1,13 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from lib import Color
|
||||||
|
|
||||||
ZERO, ONE, TWO = "012"
|
ZERO, ONE, TWO = "012"
|
||||||
|
|
||||||
BLACK = 0
|
BLACK = ZERO
|
||||||
WHITE = 1
|
WHITE = ONE
|
||||||
|
|
||||||
color = {WHITE : u"\u2B1C",
|
|
||||||
BLACK : u"\u2B1B"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
encode = {WHITE : Color.WHITE, BLACK : Color.BLACK}
|
||||||
|
|
||||||
class Image:
|
class Image:
|
||||||
def __init__(self, data, w, h):
|
def __init__(self, data, w, h):
|
||||||
|
@ -31,7 +30,7 @@ class Image:
|
||||||
return '\n'.join(image[i:i+w] for i in range(0, len(image), w))
|
return '\n'.join(image[i:i+w] for i in range(0, len(image), w))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr(self).replace(ZERO, color[BLACK]).replace(ONE, color[WHITE])
|
return repr(self).replace(BLACK, encode[BLACK]).replace(WHITE, encode[WHITE])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
57
day10.py
57
day10.py
|
@ -1,64 +1,33 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from math import gcd
|
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from itertools import product
|
from itertools import product
|
||||||
from functools import total_ordering
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from lib import vector
|
||||||
|
|
||||||
ASTEROID = '#'
|
ASTEROID = '#'
|
||||||
|
|
||||||
def zrange(x, y, step):
|
|
||||||
if x == y == step == 0:
|
|
||||||
def yzero():
|
|
||||||
while True:
|
|
||||||
yield 0
|
|
||||||
return yzero()
|
|
||||||
return range(x, y, step)
|
|
||||||
|
|
||||||
def angle(v):
|
def angle(v):
|
||||||
if v.x == 0:
|
x, y = v
|
||||||
return (2 * int(v.y > 0), 0)
|
if x == 0:
|
||||||
halve = 1 if v.x > 0 else 3
|
return (2 * int(y > 0), 0)
|
||||||
return (halve, Fraction(v.y, v.x))
|
halve = 1 if x > 0 else 3
|
||||||
|
return (halve, Fraction(y, x))
|
||||||
|
|
||||||
def rebase(base, vectors):
|
def rebase(base, vectors):
|
||||||
return (v - base for v in vectors if v != base)
|
return (v - base for v in vectors if v != base)
|
||||||
|
|
||||||
@total_ordering
|
class Map(list):
|
||||||
class Vector:
|
|
||||||
def __init__(self, x, y):
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
def __add__(self, other):
|
|
||||||
return Vector(self.x + other.x, self.y + other.y)
|
|
||||||
def __sub__(self, other):
|
|
||||||
return self + Vector(-other.x, -other.y)
|
|
||||||
def __eq__(self, other):
|
|
||||||
return self.x == other.x and self.y == other.y
|
|
||||||
def __lt__(self, other):
|
|
||||||
return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)
|
|
||||||
def __str__(self):
|
|
||||||
return str((self.x, self.y))
|
|
||||||
def __repr__(self):
|
|
||||||
return str(self)
|
|
||||||
|
|
||||||
class Map:
|
|
||||||
def __init__(self, map):
|
|
||||||
self.map = map
|
|
||||||
|
|
||||||
def __getitem__(self, v):
|
|
||||||
return self.map[v.y][v.x]
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '\n'.join(self.map)
|
return '\n'.join(self.map)
|
||||||
|
|
||||||
def is_asteroid(self, v):
|
def is_asteroid(self, v):
|
||||||
return self[v] == ASTEROID
|
x, y = v
|
||||||
|
return self[y][x] == ASTEROID
|
||||||
|
|
||||||
def vectors(self):
|
def vectors(self):
|
||||||
X, Y = len(self.map[0]), len(self.map)
|
X, Y = len(self[0]), len(self)
|
||||||
return (Vector(x, y) for x, y in product(range(X), range(Y)))
|
return (vector(v) for v in product(range(X), range(Y)))
|
||||||
|
|
||||||
def asteroid_vectors(self):
|
def asteroid_vectors(self):
|
||||||
return filter(lambda v: self.is_asteroid(v), self.vectors())
|
return filter(lambda v: self.is_asteroid(v), self.vectors())
|
||||||
|
@ -94,8 +63,8 @@ def partI(packed):
|
||||||
|
|
||||||
def partII(packed):
|
def partII(packed):
|
||||||
asteroid_map, asteroid, _ = packed
|
asteroid_map, asteroid, _ = packed
|
||||||
v = asteroid_map.vaporize_seq(asteroid)[199]
|
x, y = asteroid_map.vaporize_seq(asteroid)[199]
|
||||||
return 100*v.x + v.y
|
return 100*x + y
|
||||||
|
|
||||||
from main import Tests
|
from main import Tests
|
||||||
|
|
||||||
|
|
68
lib.py
68
lib.py
|
@ -2,11 +2,23 @@
|
||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
# Random definitons ---------------------------------------
|
||||||
|
class Color:
|
||||||
|
WHITE = u"\u2B1C"
|
||||||
|
BLACK = u"\u2B1B"
|
||||||
|
|
||||||
# Iterator recipes ----------------------------------------
|
# Iterator recipes ----------------------------------------
|
||||||
def last(iterator):
|
def last(iterator):
|
||||||
|
"""Exhausts an iterator and returns its last element."""
|
||||||
return deque(iterator, maxlen=1)[0]
|
return deque(iterator, maxlen=1)[0]
|
||||||
|
|
||||||
|
def exhaust(iterator):
|
||||||
|
"""Exhausts an iterator."""
|
||||||
|
deque(iterator, maxlen=0)
|
||||||
|
|
||||||
|
# Custom collections --------------------------------------
|
||||||
class defaultlist(list):
|
class defaultlist(list):
|
||||||
"""Default list class. Allows writing and reading out of bounds."""
|
"""Default list class. Allows writing and reading out of bounds."""
|
||||||
def __init__(self, lst, val_factory):
|
def __init__(self, lst, val_factory):
|
||||||
|
@ -24,16 +36,56 @@ class defaultlist(list):
|
||||||
return super().__getitem__(i)
|
return super().__getitem__(i)
|
||||||
|
|
||||||
|
|
||||||
def memoize(f):
|
# Basic linear algebra ------------------------------------
|
||||||
cache = dict()
|
class vector(tuple):
|
||||||
def memf(*args):
|
"""Vector class. Convert iterator to vector."""
|
||||||
key = tuple(args)
|
def __neg__(self):
|
||||||
if key not in cache:
|
return vector(-x for x in self)
|
||||||
cache[key] = f(*args)
|
|
||||||
return cache[key]
|
|
||||||
return memf
|
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
o = tuple(other)
|
||||||
|
if len(self) != len(o):
|
||||||
|
raise ValueError("vectors have different lengths")
|
||||||
|
return vector(x + y for x, y in zip(self, o))
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
return self + (- vector(other))
|
||||||
|
|
||||||
|
def __mul__(self, other):
|
||||||
|
if type(other) == int:
|
||||||
|
return vector(other * x for x in self)
|
||||||
|
o = tuple(other)
|
||||||
|
if len(o) != len(self):
|
||||||
|
raise ValueError("vectors have different lengths")
|
||||||
|
return sum(x * y for x, y in zip(self, o))
|
||||||
|
|
||||||
|
def __truediv__(self, d):
|
||||||
|
return vector(x/d for x in self)
|
||||||
|
|
||||||
|
__radd__ = __add__
|
||||||
|
__rmul__ = __mul__
|
||||||
|
|
||||||
|
def __rsub__(self, other):
|
||||||
|
return other + (-self)
|
||||||
|
|
||||||
|
def rotate90pos(v):
|
||||||
|
"""Rotates vector v by 90 degrees in positive direction."""
|
||||||
|
x, y = v
|
||||||
|
return vector((-y, x))
|
||||||
|
|
||||||
|
def rotate90neg(v):
|
||||||
|
"""Rotates vector v by 90 degrees in negative direction."""
|
||||||
|
x, y = v
|
||||||
|
return vector((x, -y))
|
||||||
|
|
||||||
|
class Cardinals(Enum):
|
||||||
|
UP = vector((0, 1))
|
||||||
|
DOWN = vector((0, -1))
|
||||||
|
LEFT = vector((-1, 0))
|
||||||
|
RIGHT = vector((1, 0))
|
||||||
|
ORIGIN = vector((0, 0))
|
||||||
|
|
||||||
|
# Graphs ---------------------------------------------------
|
||||||
class Graph(dict):
|
class Graph(dict):
|
||||||
nodes = dict.keys
|
nodes = dict.keys
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue