Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add adv_2024_22 #91

Merged
merged 1 commit into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions solutions/adv_2024_22.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import math
import functools


def _parse_input(in_str: str) -> list[int]:
return [int(_) for _ in in_str.splitlines()]


def _mix(val: int, secret: int) -> int:
return val ^ secret


def _prune(val: int) -> int:
return val % 16777216


def _mix_and_prune(val: int, secret: int) -> int:
return _prune(_mix(val, secret))


def next_secret(secret: int) -> int:
secret = _mix_and_prune(secret * 64, secret)
secret = _mix_and_prune(math.floor(secret / 32), secret)
return _mix_and_prune(secret * 2048, secret)


@functools.cache
def _all_secrets(secret: int) -> list[int]:
res = [secret]
cur_val = secret
for _ in range(2000):
cur_val = next_secret(cur_val)
res.append(cur_val)
return res


def solve_a(in_str: str) -> int:
return sum(
_all_secrets(
_,
)[-1]
for _ in _parse_input(in_str)
)


def _prices(secret: int) -> list[int]:
return [_ % 10 for _ in _all_secrets(secret)]


def _changes(prices: list[int]) -> list[int]:
return [_n - _p for _n, _p in zip(prices[1:], prices)]


def _possible_prices(
prices: list[int], changes: list[int]
) -> dict[tuple[int, int, int, int], int]:
res = {}
for _ in range(len(changes) - 3):
pattern = (changes[_], changes[_ + 1], changes[_ + 2], changes[_ + 3])
if pattern not in res:
res[pattern] = prices[_ + 4]
return res


def solve_b(in_str: str) -> int:
results: dict[tuple[int, int, int, int], int] = {}
for _ in _parse_input(in_str):
prices = _prices(_)
for _k, _v in _possible_prices(prices, _changes(prices)).items():
results[_k] = results.get(_k, 0) + _v
return max(results.values())
29 changes: 29 additions & 0 deletions tests/test_adv_2024_22.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import pytest

import solutions.adv_2024_22 as sol
from . import test_utils as tu


@pytest.mark.parametrize(
("secret", "expected"),
[
(123, 15887950),
(15887950, 16495136),
(16495136, 527345),
(527345, 704524),
(704524, 1553684),
(1553684, 12683156),
(12683156, 11100544),
(11100544, 12249484),
(12249484, 7753432),
(7753432, 5908254),
],
)
def test_next_secret(secret: int, expected: int) -> None:
assert sol.next_secret(secret) == expected


_INPUTS = tu.get_inputs(22, {"small", "p"})

test_solve_a = _INPUTS.get_test(sol.solve_a, {"small": 37327623, "p": 17005483322})
test_solve_b = _INPUTS.get_test(sol.solve_b, {"p": 1910})
Loading
Loading