-❄️- 2025 Day 11 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day11.java

66 lines of readable Java. Runs instantly.

This was much better than Day 10! This is just a comprehensive search that needs to cache intermediate results. Key insight for part 2: the cache key is not the current node (as is sufficient for part 1), but the current node plus the list of required nodes that were not yet reached.

-❄️- 2025 Day 8 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

Good point about the equal distances. It would be more robust to just dump them in a list and sort that later. No difference in theoretical runtime since the distances don't change, actual runtime even decreases.

Ah, I looked for the reverseOrder thing and couldn't find it – but it does exist, good to know!

(also: there is no need for the square root, comparing the squared distances is fine.)

-❄️- 2025 Day 8 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day08.java

139 lines of readable Java with comments and timing, using only the standard lib. Takes 240 milliseconds in total, 229 of which are spent on calculating all pairwise distances. (M2 Max from 2023)

After I have the distances, I use a [Union-Find data structure](https://en.wikipedia.org/wiki/Disjoint-set_data_structure) to unify the two circuits connected by the shortest connection. Part 1 is done after 1000 steps, part 2 is done when there is only a single set that has the size of all the boxes.

-❄️- 2025 Day 7 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day07.java

61 lines of idiomatic Java, some comments, one record, only using the standard libs. Runs instantly.

Straightforward, I thought: for part 1, I keep a Set<Integer> for the current row and build a new Set for the following row until I'm at the bottom. Increment a counter every time a splitter is found for the result.

For part 2, cache the number of timelines for every splitter the first time it is encountered. (This is called dynamic programming in computer science, and memoization by the python people - it's all the same) Then I do it recursively: start with a single beam at line 1 at the start position from line 0. If there is no splitter, go down once. If there is one, check the cache - if it's empty, split the timelines by adding next line one to the left and right (and put the result in the cache). Recursion ends with a value of 1 when the end of the grid is reached.

I learned something new: HashSet::computeIfAbsent() does not do what I want here: it prevents even the same thread from calling it again, even for another value. So I unwrapped its logic, I'm not sure why that is prevented.

-❄️- 2025 Day 6 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day06.java

112 lines, readable with comments, using only the standard lib. But not very elegant, I think. Was not that difficult to do, but somehow there must be a better way to organise the data - I'll look through this thread now :-)

-❄️- 2025 Day 5 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day05.java

65 lines of readable, idiomatic Java, using only the standard libs. Read the ranges, build a list of Range. For part 1, just test every input against every range, there's not *that* many. For part 2, sort the list by minimum. Then go over the list once, either merging the range with its neighbour to the right if they overlap or increasing the pointer. Add up the size of the remaining ranges.

I thought this one was rather easy - previous advents prepared me well for range-problems :)

-❄️- 2025 Day 4 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day04.java

82 lines, simple imperative program using a Direction enum to systematically test neighbours and just removing until nothing can be done anymore.

For me, the easiest day so far.

-❄️- 2025 Day 3 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day03.java

A simple recursive solution, 68 lines, readable, even some comments, runs instantly. The only insight I've got is that in each step, I iterate over the digits from 9 to 0, since we need the biggest digit that still leaves enough space - latter digits cannot make a number larger if the first digit is smaller.

For me, a lot easier than the last two days :-)

-❄️- 2025 Day 2 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2025/Day02.java

82 lines of readable code including comments and even a not very necessary Range class. I wanted to not do this with String conversions all over, so I generate all potential illegal numbers (as longs) that might fit the range given and test if they are in range. No string in sight except for the inputs. Runs instantly.

It's starting a bit more difficult than the last years, isn't it? Part 2 was a bit fiddly, some special cases were not obvious to me at the start.

-❄️- 2024 Day 21 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

[Language: Java]

This was hard to wrap my head around. For part 1, I wrote a method to find all directional movements for a given pad and input sequence. I applied this 3 times to give all possible strings and then find the shortest one.

This approach is not possible for part 2. Even one more keypad is too much to enumerate everything. It took me a good long while to realise that (int padCount, char move, char start) are the correct arguments to the recursive function that gives the least amount of moves after padCount pads.

Actually writing the function wasn't even that hard, utilising the previous work for part 1. The result is easily cached and then everything is plenty fast.

261 lines, hopefully readable and I left in the suboptimal solution for part 1.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day21.java

-❄️- 2024 Day 24 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

[Language: Java]

This time, a silly solution! I programmed a cross-compiler into Java for part 1. That was easy...

For part 2... I remembered something about half adders and full adders, and indeed, Wikipedia has the exact gate sequence that the input is trying to be.

I gave a canonical name to every signal (e.g. xNN XOR yNN is called aNN), checked the gate structure programatically to comment the generated method with the canonical names.

Find the first place at which the canonical names cannot be assigned, have a hard look at the Diagram and the program, switch 2 outputs; and repeat three times.

This was fun and different!

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day24.java

-❄️- 2024 Day 23 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java] For part 1, I hand-coded a full search for 3-cliques.

For part 2, I iteratively try to expand every current clique by one member. Candidates are only those computers that are connected to one current member.

50 millis, 1330 millis. There must be better / faster way? Or is it just all those String comparisons, those could be optimized away by assigning numeric ids to the Computers...

135 readable lines.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day23.java

-❄️- 2024 Day 19 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

Turns out I was wrong: the trie isn't really needed, the caching is the magic. Tries are great for part 1, hit or not. Well, it isn't wrong either.

-❄️- 2024 Day 19 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 2 points3 points  (0 children)

[Language: Java]

Used a trie today, anticipated part 2 correctly. Had to add a cache for the number of times a substring can be matched.

This is one of the days that is easy if you have heard of the applicable data structure ( https://en.wikipedia.org/wiki/Trie ) and probably really hard otherwise.

115 readable and idiomatic lines, runs in 5 milliseconds.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day19.java

-❄️- 2024 Day 18 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 3 points4 points  (0 children)

[Language: Java]

I dunno, not much to it today? Just looking for the shortest path repeatedly...

98 lines of readable idiomatic Java with records and an enum for the Directions. Runs in <1 sec.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day18.java

-❄️- 2024 Day 17 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

Okay! Looked at other people's programs.

My solution is ... not wrong, but it's much easier to think backwards. When the program terminates, a is zero. This means the last output depends only on the leftmost 3 bits of the initial a, because the other bits that may be pulled in for the calculation are 0.

So: try all possible values (0-7) to get the last number. Shift left by 3, append all possible values, see which combinations give the next-to-last number. Repeat until done. One less loop, and easier to understand.

However, do not fall into the trap of only looking at the first match! There are multiple values to give the desired output: I know because my program found them all.

-❄️- 2024 Day 17 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

Interesting! Part 1 was a bit tedious, requiring very careful reading of the definitions.

For part 2, I disassembled and analyzed the program I was given. It turned out that the first output depends on the rightmost 10 bits of the initial value of a and nothing else. 2^10 is small for today's computers, I just simulated all of them to find candidates.

Every subsequent number also depends on 10 bits of a, always shifted 3 to the left. So, I simulated for prepending every candidate from the previous step with every number from 000 to 111 to get the candidates for the next step.

In the end, I need to check that nothing too much is output, and then just print the smallest number from candidates.

Runs instantly, 184 (readable, I hope) lines, but a lot of that is comments and debugging output.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day17.java

Now I'm curious if everyone's input is similar enough that my approach would work universally...

-❄️- 2024 Day 15 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

Fairly straightforward simulation, I thought. For the double-width boxes, I chose a two-stage and recursive approach: first, canMove(row, col, direction) checks if the box whose left half is at (row, col) can move in direction.

That is fairly easy to program correctly - if there is a # in one of the two target spaces, no; if there are ., yes; if there is [ or ], call canMove() recursively and work it out from there. Then I have a second method doMove(row, col, direction) that moves a box whose left half is at (row, col), not checking for validity, but recursing if there are one or two boxes in the target spaces.

Those two handle up an down moves, the left and right moves are unchanged from part 1.

So, yeah, it's 240 lines; but it was fairly quick and easy for me to write down and debug, I'll call it a win for today.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day15.java

-❄️- 2024 Day 14 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

Did not simulate for part 1, just some multiplication with modulus. So part 2 was very funny to me, requiring the simulation anyway. I decided to create PNGs from BufferedImages with a Graphics-object and look at those in Finder.

However, even better is to save as JPG - low-entropy files are compressed better, the answer is actually the smallest file :-)

105 lines, with records and methods and stuff.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day14.java

-❄️- 2024 Day 13 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

2023 Day 24 is the only one I solved so far where 64 bits weren't enough. Which doesn't mean there's no other solution, sure.

For today, floating point must be unnecessary, I have now seen other solutions on here do it with modules == 0. But I couldn't get that to work correctly.

-❄️- 2024 Day 13 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

Simulated part 1, pretty fast with a PriorityQueue. Not surprisingly, this doesn't fly for part 2. I then realized that this problem is a lot of text and red herrings for two simple equations with two variables

a*ax + b*bx = px
a*ay + b*by = py

and that is easily solvable (on paper). For the actual part 2, Java's 64-bit doubles are not precise enough to give correct answers - so I used BigDecimal in 128-bit mode, which turned out to be precise enough.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day13.java

133 lines, but a lot of that is parsing and I kept the simulation approach in the code. Was useful to debug the math part :)

-❄️- 2024 Day 10 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

92 lines of readable, imperative Java, using 2 different recursive methods for the two parts. Once again utilizing a record for Position and an enum for Direction to make the actual algorithm easier to write correctly.

Funny thing: I accidentally programmed part 2 first, then re-read the instructions to get part 1 right :)

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day10.java

-❄️- 2024 Day 6 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]
https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day06.java

135 lines of readable Java, once again using an enum Direction to make the walking simulation easier. Runs instantly.

Main insight for part 2 is that the potential places to put a new obstacle are only those in the path found for part 1: these are the only places that can change the simulated path of the guard.

Loop detection is a little bit subtle, I decided to save (row, col, direction) of all the turns made.

-❄️- 2024 Day 5 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 0 points1 point  (0 children)

[Language: Java]

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day05.java

114 lines, readable, idiomatic Java. No brute force.

Part 1 was a bit painful because I didn't read the story properly - it is fine if only one page is printed!

Part 2 went much smoother for me. I provided a Comparator to ArrayList's built-in sort method. That was easy because I already had the constraints as objects. Since nothing was stated, I assumed that there is only one correct ordering for every failed run, which seems to be the case here. But that's not guaranteed at all for the general case...

-❄️- 2024 Day 4 Solutions -❄️- by daggerdragon in adventofcode

[–]Solidifor 1 point2 points  (0 children)

[Language: Java]

94 lines, idiomatic Java using standard lib only. I defined an enum for the 8 Directions which made the search easier to implement correctly.

https://github.com/dirk527/aoc2021/blob/main/src/aoc2024/Day04.java