day 10
knot hash
approach
the 256-element list stays a plain python list, and each length reverses a slice of it in place with swaps that wrap around via %. after each reversal the current position advances by the length plus a skip size that grows by one each time. part 1 runs one round with the numeric lengths and multiplies the first two elements.
part 2 lives in a shared knot-hash module (reused on day 14): the lengths are the input's character codes plus a fixed suffix, the same rounds run 64 times, every block of 16 values is xored together, and the result is printed as hex. the folder also keeps failure.py, an abandoned first attempt with a circular doubly linked list.
the trick
reversing a wrapping slice is just swapping pairs of indices taken modulo the list length.
def reverse(arr, s, l):
for i in range((l // 2) + 1):
si = (s + i) % len(arr)
ei = (s + l - i) % len(arr)
#print(si, ei)
arr[si], arr[ei] = arr[ei], arr[si]