Things I learned while doing Advent of Code 2022
itertools.accumulate
string.ascii_letters
complex
typemax
functionlocals
- Modular arithmetics
- Basic regex to find numbers
- SymPy library
- Working with
set
zip
function- Algorithms
- BFS
- DFS
itertools.accumulate
string.ascii_letters
complex
typemax
functionlocals
set
zip
functionfrom itertools import accumulate | |
my_dir = ["/", "mydir/", "my_other_dir/", "test.txt"] | |
for n in accumulate(my_dir): | |
print(n) | |
# / | |
# /mydir/ | |
# /mydir/my_other_dir/ | |
# /mydir/my_other_dir/test.txt |
# Quick dict to find value of a letter | |
from string import ascii_letters | |
MAP_LETTER_PRIORITY = {} | |
for i, letter in enumerate(ascii_letters, start=1): | |
MAP_LETTER_PRIORITY[letter] = i | |
# a -> 1 | |
# b -> 2 |
# Calculate a BFS | |
def bfs(grid, start): | |
queue = collections.deque([[start]]) | |
seen = set() | |
while queue: | |
path = queue.popleft() | |
x, y = path[-1] | |
if grid[y][x] == goal: | |
return path | |
for x2, y2 in ((x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)): | |
if 0 <= x2 < width and 0 <= y2 < height and can_move(grid[y][x], grid[y2][x2]) and (x2, y2) not in seen: | |
queue.append(path + [(x2, y2)]) | |
seen.add((x2, y2)) |
import functools | |
f = {} | |
f["AA"] = 1 | |
f["BB"] = 2 | |
f["CC"] = 7 | |
g = {} | |
g["AA"] = ["BB", "CC"] | |
g["BB"] = ["AA", "CC"] | |
g["CC"] = ["BB", "AA"] | |
@functools.lru_cache(maxsize=None) | |
def maxflow(cur, opened, min_left): | |
if min_left <= 0: | |
return 0 | |
best = 0 | |
if cur not in opened: | |
val = (min_left - 1) * f[cur] | |
cur_opened = tuple(sorted(opened + (cur,))) | |
for adj in g[cur]: | |
if val != 0: | |
best = max(best, val + maxflow(adj, cur_opened, min_left - 2)) | |
best = max(best, maxflow(adj, opened, min_left - 1)) | |
return best | |
result = maxflow("AA", (), 30) | |
print(result) |
# To iterate on input file | |
# $ python a.py < input.txt | |
# If file is a one-line string | |
for c in input(): | |
print(c) | |
# If file is multilines | |
for line in open(0).read().splitlines(): | |
print(line) |
message = "00011100" | |
result = ["".join(g) for k, g in groupby(c)] | |
print(result) | |
# ["000", "111", "00"] |
# Instead of | |
point = (5, 7) | |
x, y = point[0], point[1] | |
# Imaginary numbers | |
point = 5 + 7j | |
x, y = point.real, point.imag |
s = "root = 3 + 2" | |
exec(s) | |
print(locals()["root"]) # 5 |
a = 4 | |
biggest = 0 | |
# Instead of | |
if a > biggest: | |
biggest = a | |
# Just do | |
biggest = max(biggest, a) |
# Modular arithmetics | |
# You can divide all numbers by their lcm (least common multiple) to keep numbers small | |
math.lcm(2, 5, 6) # 30 |
# Quickly check neighbours in grid | |
# Instead of | |
if x, y+1 == "X": | |
win() | |
elif x+1, y == "X": | |
win() | |
elif x, y-1 == "X": | |
win() | |
elif x-1, y == "X": | |
win() | |
# Just do | |
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] | |
for dx, dy in dirs: | |
new_x = x + dx | |
new_y = y + dy | |
if (new_x, new_y) == (5, 5): | |
win() |
# Quickly find numbers in string | |
import re | |
result = [int(s) for s in re.findall(r"\b\d+\b", "dalue, 2 45")] | |
print(result) # [2, 45] | |
result = list(map(int, re.findall(r"\d+", "dalue, truc2sd 45"))) | |
print(result) # [2, 45] | |
# Also catch negative numbers | |
result = list(map(int, re.findall(r"-?\d+", "dalue, truc2sd 45 -3"))) | |
print(result) # [2, 45, -3] | |
# Find 4-letters words | |
result = re.findall(r"[\w]{4}", "2 cats and 3 dogs") | |
print(result) # ["cats", "dogs"] |
# Overlap sets | |
a = set([1, 2, 3]) | |
b = set([2, 3, 4]) | |
print(a & b) # {2, 3} | |
print(a | b) # {1, 2, 3, 4} |
from sympy.solvers import solve | |
from sympy import Symbol | |
x = Symbol("x") | |
print(solve("3*x - 3", x)[0]) # 1 |
# Easily add an element to a tuple | |
x = 1, 1, 1 | |
x += (3,) | |
print(x) | |
# (1, 1, 1, 3) |
# Iterate two items at a time, sliding | |
a = [1, 2, 3, 4, 5, 6, 7, 8, 9] | |
for b, c in zip(a, a[1:]): | |
print(b, c) | |
# 1, 2 | |
# 2, 3 | |
# ... | |
# In Python 3.10, you can even use itertools.pairwise | |
from itertools import pairwise | |
for b, c in pairwise(a): | |
print(b, c) | |
for j, k, l in zip(*[a[i:] for i in range(3)]): | |
print(j, k, l) | |
my_str = "abcdefghijklmnopqrstuvwxyz" | |
for x in range(4, len(my_str)): | |
print(my_str[x - 4:x]) | |
# abcd | |
# bcde | |
# .... |