Initial commit: AoC solutions 2023-2025
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+89
@@ -0,0 +1,89 @@
|
||||
import math
|
||||
import numpy as np
|
||||
from base import AoCBase
|
||||
from typing import List, Dict, Tuple
|
||||
from re import findall
|
||||
import cProfile
|
||||
|
||||
division_cache: Dict[int, Tuple[int, int]] = {}
|
||||
digits_cache: Dict[int, int] = {}
|
||||
|
||||
class Day11(AoCBase):
|
||||
def __init__(self):
|
||||
super().__init__(11) # Pass the day number to base class
|
||||
|
||||
def parse_input(self) -> List[str]:
|
||||
"""Override with specific parsing for this day."""
|
||||
return self.raw_data.strip()
|
||||
|
||||
def part1(self) -> int:
|
||||
regex = r"(\d+)"
|
||||
numbers = findall(regex, self.data)
|
||||
data = np.array(numbers).astype(int)
|
||||
data = self.blink(data, 25)
|
||||
|
||||
return len(data)
|
||||
|
||||
def part2(self) -> int:
|
||||
regex = r"(\d+)"
|
||||
numbers = findall(regex, self.data)
|
||||
data = np.array(numbers).astype(int)
|
||||
data = self.blink(data, 40)
|
||||
|
||||
return len(data)
|
||||
|
||||
def blink(self, data, blinks):
|
||||
for i in range(blinks):
|
||||
arr = np.array(data)
|
||||
|
||||
# Handle zero separately as it has special behavior
|
||||
arr[arr == 0] = 1
|
||||
|
||||
# Calculate number of digits for all elements
|
||||
digit_counts = np.vectorize(lambda x: math.floor(math.log10(abs(x))) + 1 if x != 0 else 1)(arr)
|
||||
|
||||
# Find indices of numbers with an even number of digits
|
||||
even_digit_indices = np.where(digit_counts % 2 == 0)
|
||||
|
||||
# Iterate over these indices, split the numbers, and replace them
|
||||
new_data = []
|
||||
for idx in even_digit_indices[0]:
|
||||
n = arr[idx]
|
||||
num_digits = digit_counts[idx]
|
||||
first_half, second_half = split_number_in_half(n, num_digits)
|
||||
new_data.append(first_half)
|
||||
new_data.append(second_half)
|
||||
|
||||
# Handle the rest of the numbers that do not meet the splitting condition
|
||||
for idx in range(len(arr)):
|
||||
if idx not in even_digit_indices[0]:
|
||||
new_data.append(arr[idx] * 2024 if arr[idx] != 0 else 1)
|
||||
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
def count_digits(arr):
|
||||
return np.vectorize(lambda x: math.floor(math.log10(abs(x))) + 1 if x != 0 else 1)(arr)
|
||||
|
||||
precomputed_divisors = {i: 10**i for i in range(1, 20)} # Adjust the range as needed
|
||||
|
||||
def split_number_in_half(number, num_digits):
|
||||
key = (number, num_digits)
|
||||
if key in division_cache:
|
||||
return division_cache[key]
|
||||
|
||||
half = num_digits // 2
|
||||
divisor = precomputed_divisors.get(half, 10**half)
|
||||
|
||||
first_half = number // divisor
|
||||
second_half = number % divisor
|
||||
division_cache[key] = (first_half, second_half)
|
||||
|
||||
return first_half, second_half
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Day11()
|
||||
#solution.solve()
|
||||
cProfile.run("solution.solve()")
|
||||
Reference in New Issue
Block a user