kupuguy

Advent of Code 2024 Day 22

Dec 22nd, 2024
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.12 KB | Source Code | 0 0
  1. from pathlib import Path
  2. from typing import Sequence
  3. from collections import deque, Counter
  4. from itertools import islice
  5.  
  6.  
  7. def parse(input: str) -> list[int]:
  8.     return [int(n) for n in input.splitlines()]
  9.  
  10.  
  11. def step(secret: int) -> int:
  12.     secret = (secret ^ (secret * 64)) % 16777216
  13.     secret = (secret ^ secret // 32) % 16777216
  14.     secret = (secret ^ (secret * 2048)) % 16777216
  15.     return secret
  16.  
  17.  
  18. def nth_secret(secret: int, n: int) -> int:
  19.     for _ in range(n):
  20.         secret = step(secret)
  21.     return secret
  22.  
  23.  
  24. def part1(data: list[int], steps: int) -> int:
  25.     return sum(nth_secret(secret, steps) for secret in data)
  26.  
  27.  
  28. TEST = parse(Path("input/day22-test.txt").read_text())
  29. assert part1(TEST, 2000) == 37327623
  30. INPUT = parse(Path("input/day22.txt").read_text())
  31. part1_total = part1(INPUT, 2000)
  32. print(f"{part1_total=:,}")  # 14,726,157,693
  33.  
  34.  
  35. def sliding_window(iterable, n):
  36.     "Collect data into overlapping fixed-length chunks or blocks."
  37.     # sliding_window('ABCDEFG', 4) → ABCD BCDE CDEF DEFG
  38.     iterator = iter(iterable)
  39.     window = deque(islice(iterator, n - 1), maxlen=n)
  40.     for x in iterator:
  41.         window.append(x)
  42.         yield tuple(window)
  43.  
  44.  
  45. def prices(secret: int, steps: int = 2000) -> Sequence[tuple[int, int]]:
  46.     last = secret % 10
  47.     for i in range(steps):
  48.         secret = step(secret)
  49.         s = secret % 10
  50.         yield s, s - last
  51.         last = s
  52.  
  53.  
  54. def sequences(secret: int, steps: int = 2000) -> Sequence[tuple[str, int]]:
  55.     for w in sliding_window(prices(secret, steps), 4):
  56.         key = f"{w[0][1]}{w[1][1]}{w[2][1]}{w[3][1]}"
  57.         value = w[3][0]
  58.         yield key, value
  59.  
  60.  
  61. def sell_dict(secret: int, steps: int = 2000) -> dict[str, int]:
  62.     seq = list(sequences(secret, steps))
  63.     return dict(reversed(seq))
  64.  
  65.  
  66. def part2(data: list[str]) -> int:
  67.     bananas = Counter()
  68.     for secret in data:
  69.         d = sell_dict(secret)
  70.         bananas.update(d)
  71.  
  72.     # print(bananas.most_common(1))
  73.     return bananas.most_common(1)[0][1]
  74.  
  75.  
  76. assert part2([1, 2, 3, 2024]) == 23
  77. part2_total = part2(INPUT)
  78. print(f"{part2_total=:,}")  # 1,614
  79.  
Advertisement
Add Comment
Please, Sign In to add comment