Things I learned while doing Advent of Code 2022
itertools.accumulatestring.ascii_letterscomplextypemaxfunctionlocals- Modular arithmetics
- Basic regex to find numbers
- SymPy library
- Working with
set zipfunction- Algorithms
- BFS
- DFS
itertools.accumulatestring.ascii_letterscomplex typemax functionlocalssetzip function| from 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 | |
| # .... |