Skip to content

Instantly share code, notes, and snippets.

@tom-huntington
Last active December 25, 2023 01:54
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tom-huntington/049fc89d8b73520b7c38266caf2db360 to your computer and use it in GitHub Desktop.
Save tom-huntington/049fc89d8b73520b7c38266caf2db360 to your computer and use it in GitHub Desktop.
Notes on 4HbQ's aoc solutions

complex for 2 vectors

Arithmatic operations broadcast unlike tuples

>>> complex(1,1) + complex(2,-2)
(3-1j)

Associative array :: T -> int

Use index/find on list or string

'  BXCYAZAXBYCZCXAYBZ'.index(x[0]+x[2])
[1j,1,-1j,-1].index(dir)
'=-012'.find(s[-1])

https://www.reddit.com/r/adventofcode/comments/zac2v2/comment/iylda9n/ https://www.reddit.com/r/adventofcode/comments/zsct8w/comment/j17k7nn/ https://www.reddit.com/r/adventofcode/comments/zur1an/comment/j1l08w6/

zip(*iterable_of_iterables) as transpose

>>> concat = lambda xs: ''.join(xs) # :: [Char] -> String
>>> xs = zip(*('aA0', 'bB1', 'cC2', 'dD3', 'eE4', 'fF5', 'gG6', 'hH7', 'iI8', 'jJ9'))
>>> *map(concat, xs),
('abcdefghij', 'ABCDEFGHIJ', '0123456789')
>>> xs = zip(*('abcdefghij', 'ABCDEFGHIJ', '0123456789'))
>>> *map(concat, xs),
('aA0', 'bB1', 'cC2', 'dD3', 'eE4', 'fF5', 'gG6', 'hH7', 'iI8', 'jJ9')

chunk

Copy an iterator [iter(x)] * n

chunk = lambda x, n: zip(*[iter(x)] * n)

https://www.reddit.com/r/adventofcode/comments/zb865p/comment/izixghj/

gather args

lambda x, *y: print(type(y) is tuple)

unpack args

fn = lambda a, b, c, d: ...
fn(*iterable)

Regex to parse ints

map(int, re.findall(r'\d+', line))

https://www.reddit.com/r/adventofcode/comments/zc0zta/comment/iyug6hl/

file handle iterates over lines

>>> [*open('in.txt')]
['line 1\n', 'line 2\n', 'line 3\n']

generator expressions

flat_map = lambda f, xs: (y for ys in xs for y in f(ys))

rotate list

rotate = lambda xs, i: xs[i%len(xs):]+xs[i%len(xs):] 

head of generator expression

Take first element satisfying constraint

next(i+n for i in range(len(x)) if len(set(x[i:i+n]))==n)

https://www.reddit.com/r/adventofcode/comments/zdw0u6/comment/iz3q1hl/

Structural pattern matching

# point is an (x, y) tuple
match point:
   case (0, 0):
       print("Origin")
   case (0, y):
       print(f"Y={y}")
   case (x, 0):
       print(f"X={x}")
   case (x, y):
       print(f"X={x}, Y={y}")
   case _:
       raise ValueError("Not a point")

Default Dict

from collections import defaultdict

Default value

>>> {}.get("a", 1)
1

reverse a list

>>> "abc"[::-1]
'cba'

Strings are iterables over chars

>>> [*map(int, "123")]
[1, 2, 3]

Rotation is transposition + reverse

rot90 = lambda A: [*map(list, zip(*A[::-1]))]

https://www.reddit.com/r/adventofcode/comments/zfpnka/comment/izj36kj/

all any

fp helpers for if all true (if any true) conditionals.

in keyword

>>> x in (1,2,3)
True

<=> starship operator

starship = lambda x: x > 0 - x < 0

https://www.reddit.com/r/adventofcode/comments/zgnice/comment/izhzxb6/

fold1/scan1 is sufficient with dynamic types

Note the element type of xs (i.e. complex) does not need to be the same as start (i.e. int)

accumulate([start]+[*xs], lambda acc, el: abs(el)+acc)
reduce(lambda acc, el: abs(el)+acc, [start]+[*xs])

use prod not reduce

from math import prod

enumerate starting from

enumerate(xs, 1)

divmod

divisor, remainder = divmod(x)

modular arithmatic over lists of lists

https://www.reddit.com/r/adventofcode/comments/zjnruc/comment/izw63we/

Dict :: complex -> T over [[T]]

https://www.reddit.com/r/adventofcode/comments/zjnruc/comment/izw63we/

structural pattern matching on data types

match l, r:
    case int(), int():
    case int(), list():
    case list(), int():
    case list(), list():

functools.cmp_to_key

turns cmp function into key for use with sorted(), min(), max(), heapq.nlargest(), heapq.nsmallest(), itertools.groupby() https://www.reddit.com/r/adventofcode/comments/zkmyh4/comment/j00qay8/

for else

>>> for i in range(4):
...     print(i)
... else: print(-1)
...
0
1
2
3
-1

delete keyword

>>> x = ["apple", "banana", "cherry"]
>>> del x[0]
>>> x
['banana', 'cherry']

polymorphism over part (i.e. 1 vs 2)

f :: (int -> bool) -> int
print(f(lambda pos: pos.imag > floor),
      f(lambda pos: pos == 500) + 1)

https://www.reddit.com/r/adventofcode/comments/zli1rd/comment/j061f6z/

use default arguments for constants??

def f(check, path=[500], rock=len(blocked)):

cartesian product with generator expressions

>>> *((a,b) for a in range(3) for b in range(3)),
((0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2))

overcome tuple parameter unpacking removal

Big loss for python3

dist = lambda x,y,p,q: abs(x-p) + abs(y-q)
dist(*(1,2), *(3,4))

@functools.cache decorator

splitting work between two agents

def search(t, u='AA', vs=frozenset(F), e=False):
    return max([F[v] * (t-D[u,v]-1) + search(t-D[u,v]-1, v, vs-{v}, e)
           for v in vs if D[u,v]<t] + [search(26, vs=vs) if e else 0])

https://www.reddit.com/r/adventofcode/comments/zn6k1l/comment/j0fti6c/

lambda return tuple split accross multiple lines

lambda x, y: (complex(x-y, y-x),
              complex(x*y, x/y))

Repeated key (representing state) => cycle reached

Have to wait for equilibrium before starting caching keys https://www.reddit.com/r/adventofcode/comments/znykq2/comment/j0kdnnj/

flood fill

https://www.reddit.com/r/adventofcode/comments/zoqhvy/comment/j0oul0u/

Day 19

Replicate

>>> [1,2] * 5
[1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
>>> "ab" * 5
'ababababab'

Rotation as complex multiplication

e+d+d*x in elves for x in (0,1j,-1j)

https://www.reddit.com/r/adventofcode/comments/zt6xz5/comment/j1d7xpk/

collections.Counter is a histogram

>>> import collections
>>> collections.Counter(['a','b','c','a'])
Counter({'a': 2, 'b': 1, 'c': 1})

Counter + operator

aka Counter.update

>>> hist = Counter('aab')
>>> hist += {'a':2}
>>> hist
Counter({'a': 4, 'b': 1})

min max

a, *_ ,b = sorted(e.real for e in elves)

head tail

*a, b = s
a, *b = s

replace eval

eval(open('in.txt').read().replace('\n\n', ',').replace('\n', '+'))``

https://www.reddit.com/r/adventofcode/comments/z9ezjb/2022_day_1_solutions/iygjmei/

list.pop list.insert list.extend

Assignment Expressions

>>> print(b := True)
True
>>> type(b)
<class 'bool'>

Optionals

>>> b = True
>>> 'a'[(not b):]
'a'
>>> b = False
>>> 'a'[(not b):]
''

Switch

>>> x=1
>>> 'ab'[x%2==0]
'a'
>>> x=2
>>> 'ab'[x%2==0]
'b'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment