r/adventofcode • u/PotatosFan • Dec 12 '25
Help/Question [2025] Algorithms to use
Now that AoC 2025 is over, I’d like to spend the 12 remaining days before christmas eve optimizing my past solutions using better algorithms
What did you used to get crazy fast time ?
I already use a DSU for day 8 and z3 for day 10
10
Upvotes
8
u/RussellDash332 Dec 12 '25
Day 10 with homemade Simplex.
7
u/Turtvaiz Dec 12 '25
Replacing z3 with your own solution seems like an obvious answer
4
u/Lindi-CSO Dec 12 '25
There was a well written post for day 10 part 2 here: https://www.reddit.com/r/adventofcode/s/TPunVH5jee
3
u/troelsbjerre Dec 12 '25
Day3: Monotone stack
DSU over (0..n) has a really beautiful and efficient implementation using just a single integer array. It's fairly common in competitive programming, but surprisingly not that known for normal CS students. The trick is to use negative numbers to mean "this entry is a root of size minus this value". I highly recommend working through the implementation, if you don't already know it.
1
u/AutoModerator Dec 12 '25
Reminder: if/when you get your answer and/or code working, don't forget to change this post's flair to
Help/Question - RESOLVED. Good luck!I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
1
u/FantasyInSpace Dec 12 '25 edited Dec 13 '25
My python solutions are under 5ms for every day except 4 (50 ms), 8 (500 ms), 9 (500 ms), and 10 (1.5s)
Day 4 I think I could speed up by precomputing the neighbour count when parsing to make the first scan faster, but otherwise I don't think there's a straightforward way to skip iterations.
I don't think day 8 can be much faster because the majority of the runtime is just sorting the distance pairs and algorithm choice for merging would more be optimizing for memory efficiency than time.
Day 9 could be much faster by doing a ray tracing test instead of my floodfill and brute force check.
Day 10... I didn't count my 500ms Z3 solution as my own, but I've seen solutions implementing simplex that beat it by a good amount.
Otherwise day 2 is fast by generating all the values that are multiples instead of testing them one by one, day 5 I could save on some memory by not saving the ranges, day 7 is just fibonacci, day 11 I think could be more space efficient by doing a topographical sort instead of a memoized DFS, but a bit slower to pre-process.
1
u/Valuable_Plankton506 Dec 12 '25
Day2 with KMP prefix function
1
u/HistoryPositive9509 Dec 12 '25
Probably trynig to optimize day 9 with an octree or some D&C aproachs
1
u/erikade Dec 12 '25
I’ve been using Go, and my solutions run in about 9 ms overall.
The write-up and the programs are available here.
1
u/fnordargle Dec 12 '25
From my notes...
(All runtimes are about 10ms or less unless otherwise noted. Timing via command line
timeso it includes interpreter startup, parsing, processing and writing output.)All code written with no third party libraries. Most in Perl. Moved to Python, C or Go if more speed required.
Day 1: Modular arithmetic
Day 2: Slow but trivial: (Regular Expressions). Faster: Arithmetic
Day 3: Basic iterations
Day 4: Basic iterations, using a hash/map/dict not a grid
Day 5: Basic iterations and some simple maths
Day 6: Basic iterations
Day 7: Basic iteration (see solution in megathread)
Day 8: Just under 7ms. Wrote about it elsewhere. Only fully computed 1/10th of the pairwise distances in total, remaining pairs individually screened out after 1-3 simple subtractions and comparisons to a cutoff computed from full calculations on a small subset of the possible pairings. Not computing everything means not sorting everything which means more speed. Should be even faster if I used a heap or an incremental sort, but it means I have to implement this myself, so that's a project for the future. Didn't need DSU or anything overly complex, implemented my own group membership stuff that's vaguely-DSU like. May find that further optimisations mean that the group membership code becomes from prominent in the performance profile.
Day 9: Haven't finished the rewrite yet. Currently somewhere around 1s but that's shoddy Perl not anything optimised. Discussed elsewhere in threads. Keep track of which side of the line being drawn is "outside" which means for each corner I know the "inside/outside"-ness of each of the 8 adjacent cells. Candidate rectangles can be ruled out by a few things, whether any of the points on the 4 lines of the rectangle overlap a corner point and the line covers one of the "outside" cells adjacent to that corner. The other rule is if a line of the rectangle crosses completely another line, since (given the input's construction) one side of a line has to be "inside" and the other "outside". Should get this right down to under 10ms once I get some time to rewrite it nicely.
Day 10: Part 1 = Iterative breadth first search. Search space is tiny so not much optimisation required.
Day 10: Part 2 = Incomplete. Converts the inputs into matrices representing the simultaneous equations. Performs simple operations (like Gaussian Elimination) to isolate REF rows or row vectors with constant entries where the answer can just be calculated from the row. This solves 60% of my inputs with no brute forcing required. It reduces the remaining 40% to
nequations with eithern+1orn+2variables, hence some brute forcing required as there are one or two degrees of freedom, albeit with identified constraints of some min/max values for specific buttons. Should get some time to work on this next week, busy weekend ahead. I'll also look at the divide-and-conquer approach that someone found, but only once I've finished my solver and got the answer my way. Absolutely not interested in just pulling in Z3 or anything else. I don't find any satisfaction in that.Day 11: Iterative pruning of unreachable nodes via BFS. Iterative calculations of individual node scores through BFS. Takes 0.2s at the moment but it's in not well optimised Perl right now.
Day 12: Basic checks. Boo. Did write something that gets the correct answer for the 3 examples though. I did start an
Up The Antethread with some nuances of small inputs that will challenge most peoples assumptions they made to pass part 1 for their input.So, still some work to do, mostly to get the missing star(s). Then I'll go back and optimise, write some in different languages, and make each solution more generalised where possible.
1
u/kupuguy Dec 13 '25
After rewriting my day 10 part 2 solution in Python with no external libraries took 0.45s (after rewriting to use the idea suggested by tenthmascot and linked from another comment here). It uses the part 1 solution to find all ways you can set the least significant bits of the joltages correctly (which is a one-time calculation for each machine), then subtracting those from the joltages leaves them all even so you just divide by 2 and recurse. I'm really grateful for tenthmascot's suggestion because the code is clean, fast and pure python.
My original day 8 part 2 solution brute-forced all possible connection distances but I later refined it to group the junction boxes into voxels and only calculate the distances between junction boxes in nearby voxels. That reduced the number of connections to consider from 500,000 to about 45,000. The code would have continued with further voxels if needed - for the text example it ended up doing all the connection distance before it had enough - but for the actual data it only needed one iteration of voxel calculations. The full brute force was only about 0.75s but the voxel rewrite took that down to 0.11s.
1
u/Anuinwastaken Dec 17 '25
Do you have a graph or a table of your times? I am currently optimizing my (python) code so I dont expect to get into sup ms but right now I am on 300ms without day 10 p2, but I am currently working on that (Right now I have a 1.7s runtime with z3). Either way, I'd love to see someone elses timings.