diff --git a/2024/11/11.md b/2024/11/11.md index bcfe10a..3bdf748 100644 --- a/2024/11/11.md +++ b/2024/11/11.md @@ -82,8 +82,6 @@ will you have after blinking 25 times?* Your puzzle answer was `211306`. -The first half of this puzzle is complete! It provides one gold star: \* - ## \-\-- Part Two \-\-- {#part2} The Historians sure are taking a long time. To be fair, the infinite @@ -91,8 +89,14 @@ corridors *are* very large. *How many stones would you have after blinking a total of 75 times?* -Answer: +Your puzzle answer was `250783680217283`. -Although it hasn\'t changed, you can still [get your puzzle +Both parts of this puzzle are complete! They provide two gold stars: +\*\* + +At this point, you should [return to your Advent calendar](/2024) and +try another puzzle. + +If you still want to see it, you can [get your puzzle input](11/input). diff --git a/2024/11/solution.py b/2024/11/solution.py index 4e73f7d..541c5f2 100644 --- a/2024/11/solution.py +++ b/2024/11/solution.py @@ -6,7 +6,7 @@ sys.path.insert(0, '../../') from fred import list2int,get_re,nprint,lprint,loadFile start_time = time.time() -input_f = 'test' +input_f = 'input' part = 1 ######################################### @@ -15,94 +15,130 @@ part = 1 # # ######################################### -def rule1(number:int): - if number == 0: - return 1 - else: - print('Number not 0, why are you here') +# 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): - # Convert the number to a string - num_str = str(number) - length = len(num_str) - - # Calculate the split index - middle = length // 2 - - # Split the number into two parts - left_part = num_str[:middle] - right_part = num_str[middle:] - #print(left_part,right_part) - - return int(left_part), int(right_part) + 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): - # Rule 1 if inst == 0: new_inst.append(1) else: - # Rule 2 - t = list(str(inst)) - if len(t) % 2 == 0: + if len(list(str(inst))) % 2 == 0: new_inst += rule2(inst) else: - # Rule 3 new_inst.append(instructions[idx] * 2024) instructions = new_inst new_inst = [] - print(len(instructions)) + 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() -part1(input_f) -print("--- %s seconds ---" % (time.time() - start_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): - dq = [] + numbers = [] with open(input_f) as file: - dq = deque(file.readline().strip().split(' ')) - new_inst = deque([]) + numbers = file.readline().strip().split(' ') - for r in range(75): - i = 0 - while_time = time.time() - - while i < len(dq): - if dq[i] == 0: - # Rule 1 - new_inst.append(1) - else: - # Rule 2 - if len(str(dq[i])) % 2 == 0: - - x = rule2(dq[i]) - new_inst.append(x[0]) - new_inst.append(x[1]) - - else: - # Rule 3 - new_inst.append(int(dq[i]) * 2024) - i += 1 - - dq = new_inst - new_inst = deque([]) - print(r,len(dq),"--- %s seconds ---" % (time.time() - while_time)) - - #print() - print(len(dq)) + result = 0 + for i in numbers: + result += genNewNumbers(i,75) + return result start_time = time.time() -part2(input_f) -print("--- %s seconds ---" % (time.time() - start_time)) +print('Part 2:',part2(input_f), '\t(cache)\t', round((time.time() - start_time)*1000), 'ms') \ No newline at end of file diff --git a/README.md b/README.md index b4a5f6c..7b59de5 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ |~~..--. _____ | |* /~\ '.| | - / .'| 8 ** '---' ||[][]_\-| |~/ * \ :| | *..' | 9 ** |------- | | /\ .'| |'''~~~~~| 10 ** + |.......|| |/\ ..' | | . | 11 ** ## 2023