* Prep Advent of Code 2023 * Solve 2023:01 "Trebuchet?!" Turns out re methods are non-overlapping. And in true AoC manners, no provided test cases had overlaps. Luckily for me, some of the last lines in the input contained the string "oneight", so I was able to find it out quite fast. Revisions: 1) Reverse strings to find last digit 2) Use isdigit() and skip regex. 3) Use regexp with positive look-ahead. * Solve 2023:02 "Cube Conundrum" Very intermediate pythonic solution, regex would have made the code more compact. But since 2023:01 decreased the regex courage, This code will do. * Solve 2023:03 "Gear Ratios" Overslept, took about 55 mins. * Solve 2023:04 "Scratchcards" On a train that according to swedish tradition was late. Not a good environment to focus. Got stuck 2 times: - Initial code asumed the | was always after the 5th number, because of the example. Puzzle input had it at pos 10. Classic AoC mistake. - I had a hard time trying to understand the score count, I insisted there was meant to be a +1 at some point. > That means card 1 is worth 8 points (1 for > the first match, then doubled three times for > each of the three matches after the first) I should instead have just looked at the numbers. * Solve 2023:05 "If You Give A Seed A Fertilizer" Part 2 takes 66 minutes to run. There is some smart things to realize here. * Solve 2023:06 "Wait for it" * Solve 2023:07 "Camel Cards" * Solve 2023:08 "Haunted Wasteland" Part 2 would have taken 10-15 hours with brute force. After I figured out the puzzle input had circular A-Z paths, it was plain as day that LCM was the solution to the problem. https://en.wikipedia.org/wiki/Least_common_multiple * Solve 2023:09 "Mirage Maintenance" * Remove parse_input helper * Refactor 2023:05 Increasing speed from 66mins to 4mins. Caching the location value in the code to keep things at highest speed. From the subreddit, the algorithm looks like this. 1. Start att location 0 2. Traverse the whole process backwards, by reversing process steps and flipping dest/src positions. 3. Output is not a location, instead it's a seed. 4. if seed is in any seed range, use seed to get location as in step 1. 5. If not, increase location by 1 and repeat 2-4. * Solve 2023:10 "Pipe Maze" Got completely stuck on part 2. Tried some polygon area calculations, but none provided the correct answer, most likely due to the unorthodox polygon points. I also tried _shoelace method_ without any luck. Had not heard about that one earlier, it was a good learning experience even though I vould not use it here. By the subreddit, several people had had luck using the ray method. > Part 2 using one of my favorite facts from > graphics engineering: lets say you have an > enclosed shape, and you want to color every > pixel inside of it. How do you know if a given > pixel is inside the shape or not? Well, it > turns out: if you shoot a ray in any direction > from the pixel and it crosses the boundary an > _odd number_ of times, it's _inside_. if it crosses > an even number of times, it's outside. Works > for all enclosed shapes, even self-intersecting > and non-convex ones. * Fix flake8 errors for 2023:1-10 * Solve 2023:11 "Cosmic Expansion" * Solve 2023:12 "Hot Springs" * Solve 2023:13 "Point of Incidence" * Solve 2023:14 "Parabolic Reflector Dish" * Solve 2023:15 "Lens Library" WALLOFTEXT for part 2, took me 90 minutes to find this important text: > Each step begins with a sequence of letters that > indicate the label of the lens on which the step > operates. The result of running the HASH algorithm > on the label indicates the correct box for that > step. It also clarifies how part 2 and part 1 relates. * Solve 2023:16 "The Floor Will Be Lava" --------- Co-authored-by: Anders Englöf Ytterström <anders@playmaker.ai>
47 lines
1.1 KiB
Python
47 lines
1.1 KiB
Python
from math import prod, sqrt, ceil, floor
|
|
from output import answer
|
|
|
|
n = 6
|
|
title = "Wait For It"
|
|
|
|
|
|
@answer(1, "The product of all record times for all races is {}")
|
|
def part_1(presolved):
|
|
return presolved[0]
|
|
|
|
|
|
@answer(2, "The product of all record times for the single long race is {}")
|
|
def part_2(presolved):
|
|
return presolved[1]
|
|
|
|
|
|
def presolve(data):
|
|
values = data.split()
|
|
l = len(values) // 2
|
|
races = list(
|
|
map(
|
|
lambda x: (int(x[0]), int(x[1])), list(zip(values[: l + 1], values[l:]))[1:]
|
|
)
|
|
)
|
|
p1 = prod(sum(bpt * (t - bpt) > d for bpt in range(t)) for t, d in races)
|
|
t = int("".join(values[1:l]))
|
|
d = int("".join(values[l + 1 :]))
|
|
# quadratic formula:
|
|
# https://en.wikipedia.org/wiki/Quadratic_formula
|
|
l = ceil((-t + sqrt(t**2 - 4 * d)) / -2)
|
|
h = floor((-t - sqrt(t**2 - 4 * d)) / -2)
|
|
p2 = h - l + 1
|
|
return p1, p2
|
|
|
|
|
|
if __name__ == "__main__":
|
|
with open("./input/06.txt", "r") as f:
|
|
inp = f.read().strip()
|
|
|
|
inp = presolve(inp)
|
|
|
|
a = part_1(inp)
|
|
b = part_2(inp)
|
|
|
|
assert a == 1083852
|
|
assert b == 23501589
|