#!/bin/python3 import sys,time,re from pprint import pprint from collections import deque sys.path.insert(0, '../../') from fred import list2int,get_re,nprint,lprint,loadFile start_time = time.time() input_f = 'input' part = 1 ######################################### # # # Part 1 # # # ######################################### # Part 1 was first done using a list and each # number in the input list was converted to ints # then each new list was created and passed through # again. # I also did the Part 1 using deque, but this wasn't # any faster at all. def rule2(number): num_str = str(number) middle = len(num_str) // 2 return [int(num_str[:middle]), int(num_str[middle:])] def part1(input_f): instructions = [] with open(input_f) as file: instructions = list2int(file.readline().strip().split(' ')) new_inst = [] for x in range(25): for idx,inst in enumerate(instructions): if inst == 0: new_inst.append(1) else: if len(list(str(inst))) % 2 == 0: new_inst += rule2(inst) else: new_inst.append(instructions[idx] * 2024) instructions = new_inst new_inst = [] return len(instructions) def part1_dq(input_f): dq = [] with open(input_f) as file: dq = deque(file.readline().strip().split(' ')) new_inst = deque([]) for r in range(25): i = 0 while_time = time.time() while i < len(dq): if dq[i] == 0: new_inst.append(1) else: if len(str(dq[i])) % 2 == 0: x = rule2(dq[i]) new_inst.append(x[0]) new_inst.append(x[1]) else: new_inst.append(int(dq[i]) * 2024) i += 1 dq = new_inst new_inst = deque([]) return len(dq) start_time = time.time() print('Part 1:',part1(input_f), '\t\t\t(list)\t', round((time.time() - start_time)*1000), 'ms') start_time = time.time() print('Part 1:',part1(input_f), '\t\t\t(deque)\t', round((time.time() - start_time)*1000), 'ms') ######################################### # # # Part 2 # # # ######################################### # Part 2 was not possible using either list or deque. # I tested various calculations to see if there was a # pattern but i couldn't find one. # I started using simple recursion in hopes that # would speed it up. That was not the case. # I ended up splitting the function in two and the part # that returns a value from the rules, would be stored # in a dict where the number and the current blink count # would be the key. # If a number+blink combo was already in the dict, it # would use the already calculated result, instead # of calculating it again. # I tested using functools.cache on the rules() function # but that gave the same compute time. def rule2(number): num_str = str(number) middle = len(num_str) // 2 return [str(int(num_str[:middle])), str(int(num_str[middle:]))] def genNewNumbers(start,end): if end == 0: return 1 end -= 1 if (start,end) not in values: values[(start,end)] = rules(start,end) result = values[(start,end)] return result def rules(start,end): if start == '0': result = genNewNumbers('1',end) else: if len(start) % 2 == 0: x = rule2(start) result = 0 result += genNewNumbers(x[0],end) result += genNewNumbers(x[1],end) else: result = genNewNumbers(str(int(start)*2024),end) return result values = {} def part2(input_f): numbers = [] with open(input_f) as file: numbers = file.readline().strip().split(' ') result = 0 for i in numbers: result += genNewNumbers(i,75) return result start_time = time.time() print('Part 2:',part2(input_f), '\t(cache)\t', round((time.time() - start_time)*1000), 'ms')