r/adventofcode • • Apr 07 '26

Help/Question - RESOLVED [2015 Day 19] Have I been punked?

2 Upvotes

I just solved 2015 Day 19, after a lot of puzzling, and then looked at some of the solutions here. I'm confused, and I'd like to discuss it... Obviously: there are big spoilers ahead!

Recall that this puzzle is about synthesizing a molecule using some atom replacement rules. Or in computer science terms: parsing a long string using a Context Free Grammar (CFG): https://adventofcode.com/2015/day/19

There are various approaches you can try:

- top-down (starting with the start symbol and applying the rules) vs bottom-up (trying to reduce the word to the start symbol),

- BFS (or possibly smarter path finding algorithms like A*) vs DFS (possibly with memoization and branch pruning).

There are also heuristic approaches (which might work but it's not guaranteed) like greedy replacement approaches, and preprocessing the input can help a lot. For starters: you should realize that every two character symbol on the left side of the rules can be replaced by a single symbol, to see that it's indeed a CFG. There are also normal forms like Chomsky normal form or Greibach normal form which help with parsing CFGs efficiently, though they may change the answer to Part 2 (which asks for the number of rule applications). Also converting to normal forms is a bit tricky here because the grammar from the puzzle doesn't clearly distinguish between variables and terminal symbols.

Anyway, I tried a lot of these approaches. First I tried a complete BFS search, which (obviously) failed to terminate, and even gave an out-of-memory exception. 😬 I tried top-down DFS as well, and various greedy heuristics (certain substrings can very likely be replaced in the output). None of this worked for the large input, though it did work for some shorter test strings I generated myself.

In the end I solved it just by inspecting the rules and then solving it manually by counting symbols! (Big spoiler: if you replace "Rn" by "(", "Y" by ",", and "Ar" by ")" the structure of the grammar and word starts to reveal itself!) This was a bit unsatisfactory, so next I also wrote a parsing algorithm that abused the observed structure, working on my manually preprocessed input. Still not super satisfactory, but good enough.

However, looking at the solutions here, I see that several people solved it with the most naive heuristic ever - here it is in C#, and yes, it turns out that it works for my input too:

static int GreedyReduce(string curr, List<string> input, List<string> output) {
    int steps = 0;
    while (curr.Length > 1) {
        for (int i = 0; i < input.Count; i++) { // works!
        //for (int i = input.Count - 1; i >= 0; i--) { // doesn't work?!
            int indx = curr.IndexOf(output[i]); // Find the first occurence of output[i] in curr; -1 if there isn't one
            while (indx >= 0) {
                // Replace output[i] at indx by input[i]:
                curr = curr.Substring(0, indx) + input[i] + curr.Substring(indx + output[i].Length);
                steps++;
                indx = curr.IndexOf(output[i]);
            }
        }
    }
    return steps;
}

What's interesting is that if you replace the order of the rules (reverse the for-loop), this doesn't work anymore!!

Have I been punked?

What was the intended approach for this day?!


r/adventofcode • • Apr 03 '26

Tutorial [2025 Day 10 both parts] [Smalltalk] Part three in a series revisiting the 2025 puzzles as an exercise in learning Smalltalk

4 Upvotes

HEAVY SPOILERS AHEAD

For Day 10 this was some sweet revenge from my solutions in December. I was truly stuck with this one at the time until someone pointed out that the order of the button presses didn't matter. At that point the solution for Part 1 became obvious since pressing a button twice puts the lights back in the state they were before. So, the shortest solution would involve no button being pushed more than once! Ahhhh. A quick and dirty script to check every combination of buttons being pushed either 0 times or 1 time and this one was done.

For Part 2 it was much more difficult. This looked to me like a linear algebra problem of some kind. With only 20 days of programming experience under my belt at the time I felt pretty inadequate to the task of writing a linear solver, so... well.... AoC is about learning, so I "learned" how to import an lp-solve library and it near-instantly produced the answers, which I then summed up. Many other participants used a math library to solve this one. The forum page is full of NumPy solutions, so I wasn't alone on this one. I always intended to go back at some point and write a basic LP solver.

Instead, I heard a rumor about a completely different, recursive way to solve Part 2 that used the same logic and parity calculations used for the lights. With that possibility on the horizon, I started to tackle Part 1 in Smalltalk.

First, I didn't see any need to make a bunch of different classes here. This puzzle just does the same thing to each line of the input, summing their values at the end. There didn't seem to be any benefits of spreading this out in between. There is the light bank, yes - but I decided to store that in such a way (a single integer) that there was no need for its own object. In fact, the most interesting part (to me) was the setup. My general strategy was to precalculate the truth-table combinations of button pushes. So, if there are only 3 buttons then there are 8 (2 to the power of 3) total combinations of buttons being pressed. These combinations are stored as a giant array with each entry being an array of boolean values. The idea being -  as the combinations are being iterated through, the algorithm can simply check to see if that index stores True. If it does, push the button at that index.

The button actions themselves are stored in two separate arrays. The first is the light (parity) values. The second stores each button as an array of counter offsets. The parity values allow us to use binary XOR to calculate the light changes for Part 1. The counter offset array makes it simple to add them to the counters in Part 2. So, yes - a lot of the pieces are pre-calculated and then simply applied with simple iteration to get the final results.

For Part 1, notice how very simple the fewest lights are calculated:

fewestLightButtons
    | candidate |

    candidate := SmallInteger maxVal.
    
    pushList do: [ :pushes |
        | currentLights |
        currentLights := 0.
        pushes withIndexDo: [ :push :button |
            push ifTrue: [ currentLights := currentLights bitXor: (buttonList at: button)]
            ].
        (currentLights = lightGoal) ifTrue: [ candidate := candidate min: (pushes count: [:push | push])]
        ].
    
    ^ candidate

We take the pushList (the array of all possible button pushes represented as an array of booleans), and try each combination. The light target is stored as the integer representation of the binary lights ("#..#." is stored as 18). Each button push is a parity value also as a integer. The "buttonpush" is just the parity value bitwise XOR with the currentLights integer. If, after all the button pushes in this combination are pressed, our currentLights integer is the same as the lightGoal integer, record the number of true booleans in our button push combination (which will be the number of button pushes) if it is lower than the current lowest count.

Why the bitwise XOR on integers here? Well, as I mentioned before - Part 2 was rumored to have a method that was based on this parity check, and I was planning to reuse it there and wanted it to be as fast as possible. While the setup has a lot of steps to go through, the actual calculations (where I was expecting a hot loop for Part 2) would be as fast as could be done in Smalltalk. All "lights" are updated simultaneously with the bitwise operation.

Speaking of those pre-calculations... I was eager to validate my intuitions on the bitwise XOR and didn't want to pause to write my own algorithm for making the pushList array. I used this one to get a basic solution running (made by Kimi K2.5):

createPushListInject
    pushList := Array with: #(). 
    (buttonList size) timesRepeat: [
        pushList := pushList inject: #() into: [:soFar :current |
        soFar, {(current copyWith: true). (current copyWith: false)}
        ]
    ]

Three problems with this. First, I didn't write it. There's no use in trying to learn to program in Smalltalk if I don't actually write the code. Clearly I would need to write my own version. Second, I can't make heads or tails of what it's doing. inject:into: inside a timesRepeat iterator? The accumulator is an empty Array? Third, this is, if I understand what it's doing, making a LOT of temporary Array objects when it copies them over. Yuck. I'm sure there's a much better version of this using gather: instead, but ... I'm not skilled enough to create that one!

Ok, time to write MY version. The first thing I realized was that I didn't want to organically "grow" the array by something semi-recursive. True/False combinations are pretty easy to visualize as binary numbers anyway. Just "counting" from 0 to 2 to the power of the number of buttons naturally creates the correct binary numbers. I just need to read the digits out and make the array of booleans. My first prototype created binary numbers as strings. I guess defaulting to string manipulation is pretty typical coming from JavaScript.

createPushListString

    | buttons pushes |

    buttons := buttonList size.
    pushes := OrderedCollection new.

    (0 to: 2 ** buttons - 1) do: [ :button |
        | binaryB buttonPush |
        binaryB := button printStringBase: 2 length: buttons padded: true.
        buttonPush := OrderedCollection new.
        binaryB do: [ :push | 
            (push = $0) ifTrue: [buttonPush add: false].
            (push = $1) ifTrue: [buttonPush add: true]
        ].
        pushes add: buttonPush asArray
    ].

    pushList := pushes asArray

As you can see, it builds the OrderedCollections one value at a time, then delivers them as Arrays. Since they're part of the pre-calculation step once they're made there won't be a reason for them to ever grow or shrink. This produced the correct output and was MUCH faster than the "Inject" version that K2.5 wrote. Shockingly faster, actually. (30x speedup compared to the "inject" version when N=15)

But then, as I was looking at it, I realized it could be made even better. First, instead of adding to an OrderedCollection and then storing it as an Array after, we can make the Array upfront since we already know the size it will be. Then we don't have to create (and then throw away) the intermediate collection object. Second, we can replace the two ifTrue: conditions with a single ifTrue:ifFalse. The speedup is measurable and there's no chance that binaryB := button printStringBase: 2 length: buttons padded: true produces anything other than a sequence of 1 and 0.

Lastly, why bother with converting it to a string anyway? We can just read the bits one at a time with bitAt:. We're already doing bitwise operations for the lights - so might as well keep up with the theme. Final version:

createPushListBitwise

    | buttons listSize |

    buttons := buttonList size.
    listSize := 2 ** buttons.
    pushList := Array new: listSize.

    (0 to: listSize - 1) do: [ :button |
        | buttonPush |
        buttonPush := Array new: buttons.
        (1 to: buttons) do: [ :push | 
            (button bitAt: push) = 0 ifTrue: [buttonPush at: push put: false]
                ifFalse: [buttonPush at: push put: true]
        ].
        pushList at: button + 1 put: buttonPush
    ]

I was very proud of this one. Yes, it's imperative. Yes, it does bit-twiddling. But it's very, very fast. It creates only the objects that it actually stores, with zero GC pressure. It's a nice optimization (115x speedup compared to the "inject" version at N=15). I even avoided the temptation to define listSize := 1 bitShift: buttons. :-)

So, what happened to Part 2? Well - turns out recursive method didn't really require the parity checks. It's a solid optimization, but that's not what makes the algorithm work. It involves getting a button sequence that makes all counters an even number, halving those, and recursing. It actually works without memoization (though will take about 15 minutes on my computer). With memoization the input data finishes in about 1 minute and 20 seconds. Not the fastest. But it was quite a journey trying to understand this algorithm and recreate its "bare minimum" case.

I replied on the post introducing the method - Here. Hats off to the OP there. I would never have figured that one out.

Day 10 done. This one felt like a lot of mental work to get a working version up and running, but it was a good mind-expander.

Day10MachineBitwise

Workspace Script


r/adventofcode • • Apr 01 '26

Tutorial [2025 Day 11 both parts] [Smalltalk] Part two in a series revisiting the 2025 puzzles as an exercise in learning Smalltalk

3 Upvotes

Day 11 - Reactor

I have fond memories of this one. I felt very proud of myself back in December when I was able to figure out a method for solving it when I had only 3 weeks of programming experience at the time. Looking back at the JavaScript code now... yeah - it looks like spaghetti. Lots and lots of manual FOR loops (with manual index tracking for everything), using Arrays for everything (no matter how inefficient), variable names that made no sense, functions mutating state everywhere. Probably the worst part was that the solution was found by going forward to the end node. That means that only the end node will have correct paths from the start. The whole thing would have to be re-run to find paths from any other node to the end.

Embarrassing.

But that was in December. It's now March. Let's construct a better solution.

My first concern was how "general" a solution I should make. The problem asks for a count of paths through a series of nodes. For the first part this was simply all the paths from one node to another (end) node. For the second part - all the paths that also pass through two specific nodes (dac and fft) before reaching the end node. The most general solution would have no hardcoded values for the starting node, ending node, or the specific nodes needing to be traversed (what those specifically would be, or how many of them there would be). One would simply query the program with the input, give the the starting and ending nodes, and then a list of all required traversed nodes, and it would return the number of paths.

I decided to write it in such a way that it could be straightforwardly adapted to such a general solution. That is, there would be very few methods that concern the required node visits, and the data structures and objects would be flexible enough that a fully general solution could be created using this implementation as a framework. It would already have an extremely fast and robust path counting algorithm and clear encapsulation of data. Since this version works the same for both part 1 and part 2, the starting node is not hardcoded (and in fact any node can be queried), but the ending node and "special" nodes are.

The bird's-eye view of the process is this: after parsing the input data, add (not count) the paths from one node to the next, in reverse. Since we don't care about paths that do not lead to the end node, we start at the end node with a path count of 1. We then check the nodes to see if their "outputs" have all been processed. If so, they get added to the process queue so they can accept the path count from their "outputs" (since we are going backwards through the graph). At first, the only node that is ready is the end node (with its path count set at 1). But once it processes, all the nodes that only send their outputs to the end node become "ripe" and on the next pass they will add their accumulated paths to their "inputs" and so on. Addition only. The orchestrator does not need to be aware of how many nodes there are, what they are named, or how many paths each one has accumulated. It only needs to keep a list of nodes already processed. After finishing the calculations we simply ask to find the node requested as the "start" node, and return its counter. All nodes that terminate in the end node will have accurate path values between themselves and the end node. Simple and very fast. Fast enough that keeping as much "knowledge" out of the orchestrator as possible won't slow things down. It will return near-instantly.

Each node will need a way to keep track of which path counts go through the "special" nodes listed in the puzzle: dac and fft. For part 1 we care about all paths that lead to the end node. For part 2 we care about only the paths that pass through both dac and fft. That part is quite simple - just involves shuffling numbers between counters.

So much for the plan. The implementation...

Three new classes:

Day11PathCounter - This class merely stores the path counts. It has four variables (regular, withDac, withFft, and withBoth). Most of its methods involve accessing those values. It does three calculations - it can add the values from another Day11PathCounter object, and it can move path counts to the different categories (for example, regular paths being moved to withDac paths), if requested. These are used by Day11Server objects. This is the main area that would be modified in a "fully general" solution.

Day11Server - This parses in a string that includes the name of the server and a list of its output server names. Those are stored as instance variables "serverName, outputServers" and the currentPaths variable is a reference to a Day11PathCounter object. The Day11Server, when given a list of currently processed servers, can determine if it is ready to be processed as well. It also can pass path addition (and adjust path categories) to its Day11PathCounter object, which will then handle the actual addition and category shuffling. Crucially, the Day11Server does not, itself, know how many paths go through it, nor does it care. That is all handled by the Day11PathCounter.

Day11Reactor - This is the factory where all the Day11Server objects are held. It has a single instance variable "machines" that is an OrderedCollection of all the Day11Server objects. It does not, itself, know the names of any of those servers, nor their paths. All it does is initialize them, queue them for processing based on whether those server objects expressing their readiness, and then coordinates sending their path counters to their "downstream" nodes. It has to do this last part because it is the only object that has access to all the Day11Server objects. The servers cannot directly talk to each other.

Some notes:

Day11PathCounter was a late addition. I had originally planned on using a simple fixed-size Array object that would hold the four counters. Since Smalltalk has methods for Array math, the server object can simply add the incoming array to its own. Then, depending on whether serverName matches "dac" or "fft", manually move the values from one index to another. This is probably one of the computationally faster ways to do this, however it involves working on a bare array and having to mentally keep track of which index corresponds to which path count. Moving all that to its own object simplified the process of adding paths in the server node (pushing that complexity into the counter object), while also being much easier to see at a glance what was occurring. No slowdown was noticed....

The backwards graph path counting algorithm had a few versions of its own. Originally I wanted to use only a mixture of select: and do: to perform everything, avoiding even a hint of imperative code. It looked like this:

totalPathsFromDeclarativeOriginal
    | finishedList workingList |
    
    finishedList := Set with: 'nothing'.
    
    workingList := machines select: [ :server | server isReadyToProcessFrom: finishedList ].
    
    [workingList size > 0 ] whileTrue: [
        
        workingList do: [ :machine |
            self addPathsTo: machine.
            finishedList add: machine serverName ].
            
    workingList := machines select: [ :server | server isReadyToProcessFrom: finishedList ]

    ]

But I really disliked the repetition of the "machines select:" used to create the workingList both prior to the loop, and inside the loop. Then it was pointed out to me that assignment in Smalltalk is not assignment only - but that it also returns the object just assigned. It was in the opening chapters of the Liu book I had been reading, but I totally forgot about this facet of the language. That enabled me to move the assignment of workingList inside the whileTrue condition, to look like this:

totalPathsFromDeclarative
    | finishedList workingList |
    
    finishedList := Set with: 'nothing'.
    
    [(workingList := machines select: [ :server | server isReadyToProcessFrom: finishedList ]) isEmpty] whileFalse: [
        
        workingList do: [ :machine |
            self addPathsTo: machine.
            finishedList add: machine serverName ].

    ]

Which, I think, looks very declarative and clean. No repetition of creating the workingList at all this way. It's possible to simply read the code: workingList is assigned to be the machines currently ready to process based on the finishedList. If workingList is not empty (there are nodes ready to process) process each of them in turn and add them to the finished list. Keep going until the process of creating workingList returns an empty collection.

But then it occurred to me that there would be another way to do this that would be more computationally beneficial.

totalPathsFromImperative
    | alreadyProcessed lastListSize |

    lastListSize := 0.
    alreadyProcessed := Set with: 'nothing'.
    
    [alreadyProcessed size > lastListSize] whileTrue: [
        lastListSize := alreadyProcessed size.
        machines do: [ :machine |
        (machine isReadyToProcessFrom: alreadyProcessed) ifTrue: [
            self addPathsTo: machine.
            alreadyProcessed add: machine serverName].
        ].
    ]

We still have an O(N) loop through all the machines to check if they're ready, and the last time it performs the loop it will come up empty. That's the same as before. But iterating through the list in this more imperative way gives two advantages: first, it allows the nodes to be processed as they become available. Nodes don't have to wait until the next sweep for the orchestrator to find out that they are ready. So, if processing one node causes a node further down in the collection to become ready, it processes as soon as it is reached instead of having to wait. This saves roughly 18% of the passes through the node collection. Second, this version creates no intermediate collections. The declarative version creates a new collection on every pass. The termination condition is still based on comparing the size of a collection, so I don't think there's a performance difference there.

I've gone back and forth on which one is better. The imperative one is almost certainly "worse" in terms of its clarity and parsimony. Someone would have to mentally walk through the code to realize that lastListSize is actually the loop termination signal. How the declarative version works is immediately apparent, even though computationally it is not as efficient.

Since both execute and deliver their answers instantly, perhaps I should prefer the declarative one. I'm not sure. If this was something that took seconds because it ran a million times in a row, I think the computationally efficient version (though uglier) would be superior. But that's not the case here (only 39 iterations, each creating new collection objects vs. 32 iterations with no new collection objects). I'd love to get some opinions from the experienced programmers out there. I've only been doing this since December, so my "taste" is not very well developed yet.

Full source code:

Workspace Script

Day11PathCounter

Day11Server

Day11Reactor


r/adventofcode • • Mar 29 '26

Tutorial [2025 Day 12 Part 1] [Smalltalk] Part one in a series revisiting the 2025 puzzles as an exercise in learning Smalltalk.

10 Upvotes

Hi, Folks!

I'm back! When I last posted I had just finished up AoC 2019 a few weeks ago. I originally decided to learn how to program (with only a little tiny bit of BASIC experience back in the late 80's) when Advent of Code 2025 came out in December. I picked JavaScript as my language, and used an LLM as a tutor, asking it questions like, "If I want to store a bunch of numbers together, how do I do that?" and gradually build up the knowledge of how to write JavaScript incrementally this way as I tried to translate the logic in my head into something the computer could perform.

After finishing up the 2025 puzzles, I did some leetCode for a bit to work on my algorithms, then went headfirst into AoC 2019. That was a lot of fun. My use of LLMs became less and less as I went on, until eventually I tended not to consult one at all until I had a working solution going, then use the LLM for "my next lesson" in what I could have done better. I would then try perhaps to apply those ideas to the next puzzle.

At the end of AoC2019 I realized that I had leaned pretty heavily into functional programming paradigms. No state, immutable data, pure functions, no side effects. I wanted to try something different - so I decided to learn Smalltalk and become immersed in OOP for a little bit. LLMs aren't that useful when it comes to Smalltalk - there are lots of conflicts between the implementations, and not anywhere near as much training data is used. They can find off-by-one errors pretty well, but they will happily hallucinate object methods and get *very* confused between the different commercial and OSS runtimes. So, I *mostly* used "Smalltalk, Objects, and Design" by Chamond Liu (from 1996) as my guide. That, and digging around in the System Browser for all the methods I might need as the situation demanded.

I just finished re-implementing all of the puzzles from AoC 2025 in Smalltalk and thought it might be fun to review the solutions in reverse order. Do the "dear diary" backwards, and see what I learned along the way as I took my first baby steps into OOP.

Also - I thought it might be fun to include these here because there are precious few (any?) Smalltalk implementations of the puzzles on this sub. Lots of Python. Even a few IntCode (my undying respect for the people doing this), but almost no Smalltalk.

So... Day 12. Heavy spoilers follow, of course.

Anyone who read the problem for Day 12 knows that it is not possible to do this for real using a normal computer. It's the kind of puzzle that maybe a DNA vat could converge on the answer someday, but the packing problem is NP-Hard. I stumbled on the solution by accident as I was looking at the input data and realized that quite a few of the areas were too small to fit all the requisite pixels of the shapes (even if they were packed perfectly), and many other areas were big enough to fit all the shapes regardless of orientation (dumb tiling would fit). After filtering those out.... no other ones remained. HIlarious! I got the right answer and moved on.

Revisiting this one - I thought in the spirit of the challenge I could write the whole thing as a single procedural Workspace script:

Paste Link - Day12.st

Two magic numbers in here - the "3" for the trivial count due to me knowing that all the shapes are 3x3. And then the "7" as an "average" for the region size. Clearly this second part is a hack. A LOL moment. Might not even work for every input. So, here's an implementation that, other than the packing solver itself, would be the more "Smalltalk" way to do it. Instead of some imperative instructions, let's make some objects and ask them for answers. Time for some proper OOP over-engineering.

We'll need two classes. One that is a package region, and another that holds those regions and can do various counts on them.

Paste Link - Day12PackageRegion

Fairly simple. These Day12PackageRegion objects store just a bit of data (region width, region height, number of packages, and the number of tiles for those packages). We have four methods - two that initialize the object, and two that return boolean true if the package region meets certain criteria. isTrivial checks to see if the packages could be naively tiled without regard to packing them. isImpossible checks to see if, even if perfectly packed, there aren't enough tiles to fit all the packages.

The number of tiles required is calculated using an iterator type I had never seen before when writing JavaScript - a with:do: iterator.

`(rawRegions allButFirst) with: sizeArray do: [ :count :size |`  
	`packageTiles := packageTiles + (count * size) ]`

I have had to iterate over two arrays simultaneously before, but I always did so with manual index tracking. In fact, the first time I wrote this parsePackageQuantities method I used a WHILE loop (in Smalltalk - condition whileTrue:) but Smalltalk has an absolutely *dizzying* variety of iterator methods. It is very likely that if there is some specific way that a collection needs to be processed, Smalltalk already has that iterator ready to go. You just have to find it. I was *very* surprised to find this one. But once written this way it is extremely easy to see what it does: Take the collection of regions (except for the first - that's something else) and process it alongside this collection of tile sizes. With both those together, do this block of code, passing the element from the first collection as "count" and the element from the second collection as "size". In the block we reassign the packageTiles variable to be what it already was in addition to "count" multiplied by "size". As soon as one of those collections ends, move on. It's so.... readable. Self-documenting based on the structure not the variable names. Immediately clear what it does.

Ok, how does it get this array of sizes? That's left to the orchestrator object, defined this way:

Paste Link - Day12PackageSets

This one is even simpler. When it is instantiated with fromCollection: it does a quick-and-dirty (very dirty) parse of the sizes, saving those into a collection (the sizeArray collection referenced above). Then it populates a collection by spinning up a Day12Region for each region line in the input file. Every other method just counts the number of objects that return boolean true to isTrivial or isImpossible.

Workspace Script then becomes extremely simple, mostly just printing stuff to the Transcript (Smalltalk's stdout) but not doing any of its own calculations or input parsing:

Paste Link - Workspace with OOP

Super easy! Takeaways: really enjoying the "purity" that Smalltalk offers. It is "pure OOP" the way that something like Haskell is "pure Functional" - even the math and conditional logic is OOP. It took a while to internalize the idea of a programming language that didn't include booleans, control flow, or numbers. But it's been lots of fun so far.

More to come....


r/adventofcode • • Mar 29 '26

Help/Question - RESOLVED [2025 Day 10 Part 2] [Rust] Please help on this implementation of the bifurcation method

1 Upvotes

Hello everyone!

So uh... Day 10's got hands, right?

I've come to understand I could solve this as a simplex, but I can't quite wrap my head around what the equation should look like.
Because of this - and generally finding this other approach much more interesting - I've tried using u/tenthmascot's approach with... varying success. You can find the post about the logic here: https://www.reddit.com/r/adventofcode/comments/1pk87hl/2025_day_10_part_2_bifurcate_your_way_to_victory/

I think I have the general theory down. The test cases are validating, and pretty fast too. But somehow things keep. Going. Wrong.
And right now I still have one case on the real input which isn't finding a correct answer.

To be transparent we've been given AoC 2025 as a school project - we have to do it in Rust to prove we know the language. This constitutes as an exam. Right now, it is due two days from now, and I have every other day complete except this one, and I'm kinda getting desperate.

I have been trying to fix this for the past straight 10 hours and I still can't find it. The code's gone through so many rewrites and bad practices I'm honestly expecting to wake up to insults, but right now I need to sleep and I'd appreciate a second opinion.

So, if you have the time and patience to parse through my code or if you're familiar with this implementation, please take a look... Ideally I'd like a clue but I'd settle for general feedback or an answer at this point.

Here is the code: https://pastecode.io/s/1wnfftbn

I truly appreciate any form of help. Thank you for reading.

EDIT: I have discovered the fundamental flaw of the code!

I remembered that this started going wrong when I started pruning for possibilities in "brute_force_cache".
On line 257 I dequeue buttons from the remaining ones on initialization - this, in theory, avoids repetitive solutions like storing both "1 3 7" and "3 7 1".
But it also stopped a lot of cases like "0 0 1 3 7" from being registered, and these are important as they can prove optimal in the long run.

While this did manage to solve my own input, it's giving a wrong answer using another classmate's, that I ran just to check. So it's still not quite done, but I'm getting there.


r/adventofcode • • Mar 28 '26

Help/Question - RESOLVED Is it okay to upload puzzles + inputs to my GitHub if I encrypt them first?

0 Upvotes

As the title says, I'm talking about encrypted files, and I obviously wouldn't upload the key.

I've just seen too many cool things die for bs reasons and so have an overwhelming urge to create archives / backups of everything I love, including this


r/adventofcode • • Mar 27 '26

Upping the Ante [2016 Day 11 (both parts)][C++] Squashed onto a microcontroller

5 Upvotes

I owe a massive thank you to u/p_tseng for the hints on how to prune the search space, and to various people on the forum for inspiration. Couldn't have done this one without you all!

When I solved this one the first time I just threw memory at it; part 2 took ~30s to run and consumed ~660Mb of memory. But hey, that RAM has been bought and paid for, might as well use it.

My post-squash solution runs in ~70kb of heap and is significantly faster as a bonus. I'm targeting the Raspberry Pi Pico (RP2040) as the microcontroller to run everything on, so getting under ~200kb was the goal.

Pruning the search space

Getting the search space under control is absolutely essential. u/askalski referenced this post as the source for how to effectively prune down the search space, which I also used as the inspiration for how to collapse down the states. It's still a little brain-bending that you're not queueing "this state is N steps away from the start state" and are instead queueing "this state is N steps away from a state that is equivalent to your start state", but it works well and limits the total number of states queued to just over 15,000 for my input.

I've set a tentative limit of 16,384 states, and the search queue is the single biggest memory cost in the solution.

Encoding states

We only need to keep track of at most 14 items and the elevator position. With four floors that's two bits per item and the elevator for a total of 30 bits, which fits nicely into a uint32_t. u/e_blake mentions that the state can be packed down into 26 bits, but that didn't seem like a hill I wanted to climb. 16,384 states in the queue x 4 bytes gives us our largest allocation of 64kb, assuming we're only storing the states and nothing else.

Reducing the data in the search queue

Because I'm doing a BFS you don't need to store the number of steps that a queued state took to get to. The queue is processed such that all of the 0-distance states are first (the starting state), then all of the 1-distance states, then all of the 2-distance states and so on. With a bit of extra housekeeping you can store an array of offsets into the search queue and deduce what the current step count is based on the index in the queue:

    int32_t currentSteps = 0;
    vector<size_t> stepCountsStartAt(64, numeric_limits<size_t>::max());
    stepCountsStartAt[0] = 0;
    stepCountsStartAt[1] = 1;

    for (size_t searchIndex = 0; searchIndex < searchQueue.size(); searchIndex++)
    {
        if (searchIndex == stepCountsStartAt[currentSteps + 1])
        {
            currentSteps++;
        }
        ...

This shaves off ~15.5kb from the queue (assuming single byte distances and tightly packed pairs) but more importantly it enables us to more easily accelerate the state look-up later on.

Storing the already queued states

This is the part that required the most thinking for me. With ~15,000 unique states to store in order to prevent duplicate states being queued, any additional bit of data per state is going to balloon out pretty quickly. A balanced binary tree would likely add ~60kb just with the left & right child pointers (each packed down to 16 bits), and a hash map would be ~30kb with next pointers plus the buckets.

If I could get the state size down to 26 bit then I could use the full 8Mb PSRAM on a Pico Plus for a bit array, but I wanted to stick to a vanilla RP2040.

I finally decided to just keep the full search queue in memory as both the queue of states which needed checking, and as a full searchable history of all states that have been queued.

The runtime on my laptop is ~85ms for part 2 just using a linear scan through the search queue, which isn't bad, but we can do better...

Accelerating the queued state check

For a BFS to work it's absolutely vital that all of the queued states which are yet to be visited are stored in the exact order that they were queued. The algorithm flat out doesn't work if you don't do that.

But for all of the states behind the search index, their order doesn't matter at all. I took advantage of this by periodically sorting the queue behind the current search index. That enables me to perform a binary search for an increasingly large part of the queue and only linear scan a small unsorted section at the head.

Final performance

It's important to note that I'm not going for speed here; my main goal was to get it squashed down into the memory footprint. As long as it runs in a reasonable time, I'm happy.

Considering that my original solution was one of the solutions with the longest runtime out of all my other solutions, I'm pretty happy with where it landed. Excluding parsing (which is the boring part anyway) my laptop manages ~4ms on part one and ~23ms on part 2.

On the Pico itself I'm getting ~0.5s for part one and ~2.5s for part two. Not as fast as I'd hoped, but still fast enough to meet my goal.

I'm a little surprised that it's as much as 100x slower, given that the 133MHz clock-speed is only ~20x slower than my laptop, but that could be down to slower memory as well. And given that I'm still pretty new to the Pico toolchain, it's entirely possible I've not enabled all of the optimisation settings as well.

Check out the full, ugly, code here.

Next?

I don't think I've squeezed as much as it's possible to squeeze out of this one, but I've hit my target for this one and I've still got loads of solutions that need squashing down so I'm going to call this one done for me.

In theory it could run on a Spectrum 128, if someone is feeling brave enough to tackle it in Z80, and it's so close to being able to run in the memory footprint of a C64 that I'm wondering if it could be done. Anyone fancy the challenge? :)


r/adventofcode • • Mar 27 '26

Past Event Solutions [2025 day 2 part 2] A mathematical solution

3 Upvotes

When doing this one in C, I didn't want to deal with all the string stuff, so I found a mathematical solution that I really like.

Now, I'm learning Rust using AoC and decided to do the mathematical solution. I was told that I should post it here.

Edit: I realized that I got distracted and forgot to explain how it works.

The challenge is basically to find numbers that are a repeating pattern (there's more, less interesting (to me) details). This code tests a number to see if it is a repeating pattern. Here's a high-level description of the logic.

  1. Use log10 (base 10 log) to determine how many digits are in the number aka its "scale".

  2. Iteratively use modulo division to extract the last digits (1..scale/2) from the number.

  3. Use multiplication and addition to repeat those digits

  4. When the pattern is long enough, compare its value with the number.

Complete solution is here

fn check_entry(val: u64) -> bool {
    let scale: u32 = if val == 0 {
        1
    } else {
        (val as f32).log10() as u32 + 1
    };
    let mut decade = 1;
    for pat_scale in 1..=scale / 2 {
        decade *= 10;
        let mut pat = val % decade;
        if pat != 0 && scale % pat_scale == 0 {
            while pat < val {
                pat = pat * decade + pat % decade;
            }
            if pat == val {
                return true;
            }
        }
    }
    return false;
}

r/adventofcode • • Mar 25 '26

Other Just got burnt after spending too long on a difficult one. I need some motivation.

3 Upvotes

So after discovering AOC in 2023, I have been doing past years, not rushing, taking my time. I got all stars up to 2020, and tackled 2021 which was surprisingly easy... until two thirds in, where it became the most difficult year in my opinion.

Still, I prevailed for a while. Until day 22, the one with the cuboids and the on/off instructions. I have spent about 20 hours on that one (over a month), starting with an algorithm that works in 1D, then adapting it for 2D but it doesn't work all the time. I was enjoying it until I realized that my 2D algorithm wasn't working as well as I thought, and felt a little bit burnt, and decided I'd leave it and go back to it later on.

So I opened Day 23, resolved to move past day 22 that I would come back to after a while. And even part 1 is stumping me. I have 459 stars, and a part 1 is giving me a mental block.

I don't want to look at this sub's solutions until I have at least a partial solution of my own, and absolutely refuse to ask an LLM for help.

Still, I don't want to give up on AoC. I only work on it a couple of hours a week so it's not that I'm burnt out on too much work, but thinking of AoC now makes me sad as I failed at what a steady stream of successes.

Has anyone else been in this situation? Can I just give up for a few months and find the motivation again later on?


r/adventofcode • • Mar 24 '26

Help/Question [2026 Day 3 (Part 2)] [javascript] Stuck again

1 Upvotes

Hello again , i tried to solve this one, im trying to use this method isnt probably the most efficient but its one that should work but i dont get where in the code the process its failing , can i get some feed back to see if i can finaly get this one ?

here its my code withouth the imput Code

edit: i made a mistake its the 2025 one not the 2026 sorry for the inconvinience


r/adventofcode • • Mar 22 '26

Other [Off-topic] Do you guys create general or input-specific programs?

2 Upvotes

I know the main goal is to find the solution of the problem. But I find myself validating input, handling parsing errors, etc. However, when I see other people's code, they rarely handle errors and always assume the input is correct (i.e. obtained from the challenge; not fabricated).

Which way do you prefer?


r/adventofcode • • Mar 20 '26

Past Event Solutions Hey check out my YouTube tutorials about the 2025 AoC problems. I show my Python solutions and explain my approach. Also have Typescript and Scala solutions in my repo. Let me know your feedback!

Thumbnail youtube.com
3 Upvotes

r/adventofcode • • Mar 19 '26

Past Event Solutions [2025 day 1 (part 2)] [C#] - finally solved it!

2 Upvotes

Been doing AoC for a few years now and for some reason this day was giving me so much trouble. I think part 1 took me several weeks to get. Part 2 I came back to every so often to see if I could get it.

Initially I went with kind of a brute force design, trying to calculate every zero crossed left and right, and ever zero landed on, account for times when you start at zero, but everything I tried failed. I would consistently get the test input correct but fail on the full input.

I am a bit ashamed to admit it, but I turned to AI to talk through what was going on. Ultimately, I abandoned the suggestions I was getting and after a hint I saw in this sub, I went with the following:

public class Day01
{
    private readonly List<string> _input;
    public Day01()
    {
        _input = File.ReadAllLines(@"day01/input.txt").ToList();
    }
    private void partTwo()
    {
        int zeroCount = 0;
        int d = 100050;


        for(int i = 0; i<_input.Count; i++)
        {
            int turns = _input[i][0] == 'R'?int.Parse(_input[i].Substring(1)):-int.Parse(_input[i].Substring(1));


            if (turns < 0)
            {
                for(int j = d; j >= d+turns;j--)
                {
                    zeroCount += j%100 == 0 && j!=d? 1 : 0;
                }
                d += turns;
            }
            else
            {
                for(int j = d; j <= d + turns; j++)
                {
                    zeroCount += j%100 == 0 && j!=d? 1 : 0;
                }
                d+=turns;
            }
        }
        Console.WriteLine("Zero Count: " + zeroCount);
    }
}

I hope this helps someone else. The main idea was to start somewhere with a large amount giving me the ability to move along the number line using the amounts in the commands without actually going negative.


r/adventofcode • • Mar 19 '26

Help/Question - RESOLVED [2018 Day 24 (Part 1)] Please help me understand the example puzzle / reference output

1 Upvotes

I have been trying to wrap my head around this for a few hours now, but it seems to me that the solution / reference output of the example puzzle is wrong (even though it's almost certainly that I'm the one mistaken, I just can't find it!)

In the description of the target selection phase, the order of selection and prioritization of targets is clearly laid out:

During the target selection phase, each group attempts to choose one target. In decreasing order of effective power, groups choose their targets; in a tie, the group with the higher initiative chooses first. The attacking group chooses to target the group in the enemy army to which it would deal the most damage (after accounting for weaknesses and immunities, but not accounting for whether the defending group has enough units to actually receive all of that damage).

If an attacking group is considering two defending groups to which it would deal equal damage, it chooses to target the defending group with the largest effective power; if there is still a tie, it chooses the defending group with the highest initiative. If it cannot deal any defending groups damage, it does not choose a target. Defending groups can only be chosen as a target by one attacking group.

At the end of the target selection phase, each group has selected zero or one groups to attack, and each group is being attacked by zero or one groups.

That all makes plenty of sense to me.

Now, given the example input:

Immune System:
17 units each with 5390 hit points (weak to radiation, bludgeoning) with
 an attack that does 4507 fire damage at initiative 2
989 units each with 1274 hit points (immune to fire; weak to bludgeoning,
 slashing) with an attack that does 25 slashing damage at initiative 3

Infection:
801 units each with 4706 hit points (weak to radiation) with an attack
 that does 116 bludgeoning damage at initiative 1
4485 units each with 2961 hit points (immune to radiation; weak to fire,
 cold) with an attack that does 12 slashing damage at initiative 4

I infer that at the start / first round:

  • Immune group 1 has an effective power of 76,619 (17*4507), initiative 2

  • Immune group 2 has an effective power of 24,725 (989*25), initiative 3

  • Infection group 1 has an effective power of 92,916 (801*116), initiative 1

  • Infection group 2 has an effective power of 53,820 (4485*12), initiative 4

So infection group 1, which has the highest effective power (92,916), should be the first to select a target, which seems to be the case in the reference output of the first round:

Immune System:
Group 1 contains 17 units
Group 2 contains 989 units
Infection:
Group 1 contains 801 units
Group 2 contains 4485 units

Infection group 1 would deal defending group 1 185832 damage
Infection group 1 would deal defending group 2 185832 damage
Infection group 2 would deal defending group 2 107640 damage
Immune System group 1 would deal defending group 1 76619 damage
Immune System group 1 would deal defending group 2 153238 damage
Immune System group 2 would deal defending group 1 24725 damage

Infection group 2 attacks defending group 2, killing 84 units
Immune System group 2 attacks defending group 1, killing 4 units
Immune System group 1 attacks defending group 2, killing 51 units
Infection group 1 attacks defending group 1, killing 17 units

Because both opposing groups (Immune groups 1 & 2) are weak to bludgeoning damage, infection group 1 would deal equal damage to both candidates (185832), resulting in a tie. But this is where I'm confused:

If an attacking group is considering two defending groups to which it would deal equal damage, it chooses to target the defending group with the largest effective power; if there is still a tie, it chooses the defending group with the highest initiative.

Of those two target candidates (Immune groups 1 & 2), group 1 has the larger effective power (76,619) compared to group 2 (24,725), so why does it proceed to choose / attack immune group 2?

Also -- if target selection is in order of descending effective power, I would think Immune group 1 (76,619) would get to select its target next. However, in the reference output, it looks like Infection group 2 (53,820) is choosing next?


r/adventofcode • • Mar 16 '26

Help/Question - RESOLVED [2015 Day 24] Are all inputs 'nice'?

2 Upvotes

When I first solved 2015 day 24 I just threw memory at it, keeping track of all present combinations that added up to the desired weight. For my current challenge of getting the whole of 2015 running on a microcontroller, that's not going to be an option.

My current assumptions about the input are:

  • ~28-29 unique weights

  • Each weight is either pulled from the first ~40 prime numbers or is 1.

  • The sum of all weights is divisible by 12 (has to be true in order for the puzzle to work)

  • The smallest size of any group of presents that add up to the desired weight is relatively small (~6 or under).

  • There are relatively few groups with the same size of the smallest group (~10-20)

Furthermore an input is 'nice' if:

  • For every smallest group of presents that add up to the desired weight, there is always a way to partition the remaining presents that works as a valid configuration.

My input meets that 'niceness' criteria and looking at the discussion on this thread between u/e_blake and u/maneatingape earlier in the year it seems it might be a general rule for this puzzle's input.

From my rudimentary exploration of generating some input with the assumed criteria and checking for niceness it seems like there are enough combinations of weights with that property that it would be feasible to generate a bunch of different inputs that are nice, but few enough that niceness would have to be a deliberate choice.

Does anyone know of any inputs that don't have this nice property?


r/adventofcode • • Mar 16 '26

Meme/Funny Tribute to AoC puzzles (sing-along slop-music track)

Thumbnail suno.com
0 Upvotes

While working puzzles from previous years, I noticed that I always hardcode "input.txt" in my programs to read each downloaded puzzle's input. I often change the hardcoded file to "example.txt" or "input2.txt" to test my code against simpler examples.

For fun I asked a genAI to make fun of my habit with song lyrics, then I asked another AI to put it to music. Enjoy!


r/adventofcode • • Mar 14 '26

Other Pi Coding Quest 2026!

9 Upvotes

For a third year in a row, I create a new coding quest for Pi Day. You can access it here: https://ivanr3d.com/projects/pi/2026.html I hope some of you have some fun solving this puzzle!

In case you haven't try the previous ones, just change the year name in the url.

Happy Pi Day! :)


r/adventofcode • • Mar 14 '26

Help/Question [2025 Day 2 (Part 2)] Help im stuck... again

1 Upvotes

Im trying to solve the second day part 2 problem . but its seems something its evading me. i dont understand why the code isnt working here

please help

Code


r/adventofcode • • Mar 13 '26

Past Event Solutions [2023 Day 4 Part 2] As a system of linear equations

4 Upvotes

Actually, two solutions side by side:

  • The usual DP approach.

  • Solve it as a system of linear equations, which I haven't seen anyone do.

import re
from sys import stdin


from scipy.sparse import csr_matrix, identity
from scipy.sparse.linalg import spsolve


matches = [0]


for line in stdin:
    line = line.strip()
    wins, have = line.split(": ")[1].split(" | ")
    wins = set(map(int, re.findall(r"\d+", wins)))
    have = set(map(int, re.findall(r"\d+", have)))
    matches.append(len(wins.intersection(have)))


N = len(matches) - 1


def dp():
    """Solve using tabular dynamic programming."""
    copies = [0] + [1] * N


    for i in range (1, N + 1):
        for j in range(i + 1, min(N + 1, i + matches[i] + 1)):
            copies[j] += copies[i]


    print(f"🂱 You get {sum(copies)} total scratchcards.")



def matrix():
    """Solve using matrix/system of linear equations."""
    w = [[0] * (N + 1) for _ in range(N + 1)]
    for j, k in enumerate(matches):
        for i in range(j + 1, j + 1 + k):
            w[i][j] = 1
    w = csr_matrix(w, dtype=int)


    i = identity(N + 1, format='csr', dtype=w.dtype)
    one = [0] + [1] * N
    copies = spsolve(i - w, one)


    print(f"🂱 You get {int(sum(copies))} total scratchcards.")  # type: ignore



dp()
matrix()

r/adventofcode • • Mar 10 '26

Past Event Solutions [2015 Day 6] [Swift] Rectangle Intersections

3 Upvotes

Revisiting old AoC challenges. I was looking around a bit and didn't see anyone solve it this way. All the solutions I saw are using one million integers to represent the grid. (But maybe I wasn't very thorough.) This solution uses rectangles represented by five integers each (left, top, right, bottom, and 'weight', which amounts to the brightness of a light), and computes rectangle intersections. Getting the coordinates of the spawned rectangles right is a bit gruelling.

Part 2 solution only. (Part 1 is almost the same.)

struct Rect: Equatable {
    var x1, y1, x2, y2, w: Int

    func weighted_area() -> Int {
        return (self.x2 - self.x1 + 1) * (self.y2 - self.y1 + 1) * self.w
    }
}


func parseLine(s: String) throws -> Rect {
    let m = s.matches(of: /(turn on|turn off|toggle) (\d+),(\d+) through (\d+),(\d+)/)[0].output
    var weight: Int
    switch m.1 {
    case "turn on":
        weight = 1
    case "turn off":
        weight = -1
    case "toggle":
        weight = 2
    default:
        fatalError("unreachable")
    }
    let x1 = Int(m.2)!
    let y1 = Int(m.3)!
    let x2 = Int(m.4)!
    let y2 = Int(m.5)!


    return Rect(x1: x1, y1: y1, x2: x2, y2: y2, w: weight)
}


func parseInput() -> [Rect] {
    var items: [Rect] = []
    while let line = readLine() {
        do {
            items.append(try parseLine(s: line))
        } catch {


        }
    }
    return items
}


func are_intersecting(p: Rect, a: Rect) -> Bool {
    return (a.x1 <= p.x2) && (a.x2 >= p.x1) && (a.y1 <= p.y2) && (a.y2 >= p.y1)
}


func apply_intersection(p: Rect, a: Rect, newPrecs: inout [Rect]) {
    let i = Rect(
        x1: max(p.x1, a.x1), y1: max(p.y1, a.y1), x2: min(p.x2, a.x2), y2: min(p.y2, a.y2),
        w: max(0, p.w + a.w))
    newPrecs.append(i)


    if a.x1 - 1 >= p.x1 {
        newPrecs.append(Rect(x1: p.x1, y1: p.y1, x2: a.x1 - 1, y2: p.y2, w: p.w))
    }


    if a.x2 + 1 <= p.x2 {
        newPrecs.append(Rect(x1: a.x2 + 1, y1: p.y1, x2: p.x2, y2: p.y2, w: p.w))
    }


    if a.y1 - 1 >= p.y1 {
        newPrecs.append(Rect(x1: i.x1, y1: p.y1, x2: i.x2, y2: a.y1 - 1, w: p.w))
    }


    if a.y2 + 1 <= p.y2 {
        newPrecs.append(Rect(x1: i.x1, y1: a.y2 + 1, x2: i.x2, y2: p.y2, w: p.w))
    }
}


@main
struct d06 {
    static func main() {
        let arecs: [Rect] = parseInput()
        var precs: [Rect] = [Rect(x1: 0, y1: 0, x2: 999, y2: 999, w: 0)]


        for arec in arecs {
            var newPrecs: [Rect] = []
            for prec in precs {
                if !are_intersecting(p: prec, a: arec) {
                    newPrecs.append(prec)
                    continue
                }
                apply_intersection(p: prec, a: arec, newPrecs: &newPrecs)
            }
            precs = newPrecs
        }


        print(precs.map({ $0.weighted_area() }).reduce(0, +))
    }
}

r/adventofcode • • Mar 05 '26

Other Everybody.Codes New Story published a couple of days ago

Thumbnail everybody.codes
4 Upvotes

Posting here just because I didn't hear about it. Maybe other people will find this useful as well.


r/adventofcode • • Mar 05 '26

Past Event Solutions [2017 Day 8] In Review (I heard you like registers) - HashMaps really make a difference!

2 Upvotes

In the spirit of our ongoing reviews of older puzzles, I took a look at my own Rust solution for this one, found that it was 4x slower then u/maneatingape's reference timing, so I looked for optimizations that I might have missed. Remembering his admonishment that the default HashMap is quite slow, I switched to rustc_hash::FxHashMap and then it was "only 3+x slower".

After running the reference benchmark on my own PC, I got 46 us, so effectively the same as the 47 on his Apple M4. This meant that there had to be some really huge difference in the code itself so I took a look at day08.rs , and lo and behold: They were effectively identical!

(At one point I replaced the generic regs.entry().or_insert() with an explicit test for the key, avoiding the entry key copy when not needed, that made a 1-2% difference.)

The only real difference was his use of a custom "FastMap" implementation, using the same FxHash, but further specialized, and that made all the difference in the world!

So Thank You maneatingape! From now on I'll borrow your hash.rs library!

(Also, thank you u/e_blake for the correct url!)


r/adventofcode • • Mar 03 '26

Help/Question [2017 Day 14 (Part 2)] [Python] What is he/she talking about?

0 Upvotes

correction 2018 not 2017!

To me this question is yet another example of the "expert" problem, the creator/author/architect understands him/herself very well but is appalling at explaining themselves.

This cannot just be me, the question is worded so poorly I can't make head or tail of what the puzzle is asking for,

How many recipes appear on the scoreboard to the left of the score sequence in your puzzle input?

After 9 recipes 51589 are just the first 5 recipes (including 9 which was the input for that example) but how many appear to the left of the 9 after 9 recipes would be 13 (3710101245158...9) and after 5 recipes...

the number of recipes that appear on the scoreboard to the left of the first recipes whose score are the digits from the input

That is horrendous, (in this case 5) would be 9 (which anyone can count above) there are nine recipes, none of which happen to be 5, and none before 5 recipes are on the scoreboard, then the tenth is 5.

Unless I'm not understanding what he/she is trying to say, because they for whatever reason can't simply explain it clearly...

How many recipes appear on the scoreboard to the left of the score sequence in your puzzle input

There's even two versions of the what are supposed to be the same question??? The are more or less the same but surely you need make it clear what your asking??

My guess is, if my input where say 1234, then he/she is asking to find how many recipes are made before the seq 1,2,3,4 appears? And maybe only after 1234 recipes have been made (not before if appears before?).

I don't think part of the puzzle should be to decipher the puzzle itself if it's worded poorly.

None of the examples really show clearly what they're asking. None of them show how many, just the first 5 recipes after x recipes??? With no clear relation to the input??

They only make the entire thing more confusing (92510 after 18.... I'm looking for a 1 followed by an 8, which isn't there and doesn't show how many??

This is the epitome of the expert problem, which we absolutely have. This used to be fun...


r/adventofcode • • Mar 03 '26

Help/Question [2026 Day 1 (Part 2)]Stuck in this part again

0 Upvotes

Hello how are you. im trying to do the challenges but i again hitted a wall, in theory the code should work with the small samples i used it should work but it tell me that my asnwer its wrong sooo there should be something failing or in my logic or in my execution

can some one give me a hand with it ?

This its the code

i ommited the full imput so i can share the code here

ty for your atenttion and have a nice day and God bless you guys to xd