Discussion thread for day 2 of the Advent of Code - https://adventofcode.com/2025/day/2
Brute force but it worked!
Anybody found a good way to
Thankful for a 30-minute problem! This doesn't feel like a very elegant solution, but at least it's macro-free...
@aiahwieder, my thoughts:
Day 2
Might try this out and report back; fortunately the data set was strings no longer than 10 characters, but it made me long for an iterative approach!
Had to actually work, so I missed the posting. Still fun and glad I got my 2 stars again!
Ended up solving part 2 when trying to figure out the RegEx for part 1
Day 2 Solve
RegEx is my hero!
Trying to hold off using a macro until at least day 4. Let's see how that pans out.
the one Without Regex
Can never complain with a bit of RegEx! A nice day 2.
Took me longer than I'd care to admit, a good reminder to make sure your string fields are long enough for your inputs!
I could have tidied up Part 2 with a macro, but I didn't.Not pretty. Some elegant solutions using Regex I need to check out.
This one was more of a thinker for me. Took a little while to figure out what I even wanted to do, but it wasn't too bad to actually build after that!
Part 1:1) The first steps were relatively straightforward as I used a text to columns and a generate rows to create one row per "potential ID", based on the ID ranges provided in the input.
2) Potentially an unnecessary extra but I created a copy of the ID column but this time stored it as a string, so I didn't need to keep changing the datatype.
3) At this point, I simply extracted the left half and right half of the string separately. I was able to do this by simply taking the length of the string and dividing it by two. Then feeding it into the Left / Right functions.
4) I filtered to the cases where the left and right halves were equal, then summed the values.
Part 2:Step one and two were the same as in part one, but then things did differ slightly. 1) The key difference between part one and two, is that the "repeated" string could be of any length. However we can deduce, in order for a string to be classed as repeated, it must appear at least twice, hence the length of the repeated pattern cannot exceed, half the length of the overall string. i.e- If we look at ID 123123, we know that the "repeated string" has to be at most, 3 characters long, (a "repeated string" of 4 characters, would create an answer 8 character long, when repeated, therefore would not work for this example)- "1", "12", and "123", are the only 3 we need to considerTo consider these cases in isolation I needed one row per case, so I used the generate rows to create these extra lines (counting up, until I got to half the length of the original string):
2) Now I could create the the potential "repeated strings", on their separate lines, by using the Left() function. Then replaced all occurrences of the "repeated string" in the ordinal ID column, with nothing. If the cell in the ID columns was left completely blank, then I knew the pattern must have repeated throughout the whole ID. Using the same example as before I would get the following.
Edit: If I were to go back and redo the question, having seen other peoples solutions, I would like to use the regex "\1$". It appears to represent one repetition of the group previously defined. I'd never seen it before today so thanks all for the new regex trick!
Suspiciously straightforward...
I first used Text to Columns to split on the comma, then split to rows on the dash. I then generated rows between the two parts of the ID:
I then used some sexy Regex to identify first matches of two characters, then two or more:
Then simply summed the IDs for each match.
Whenever I do the first couple of days quickly I feel it's written specifically to hurt me.
M.
I, like others, found this challenge to be easier mentally to figure out than Day 1, but I could see where others might disagree. It's a different skillset to solve this than the first day's. Anyway...
Here’s my solution:
Narrative:
It was easy enough to parse the data, splitting it by comma, then by the dash. From there, filling in the ranges, etc.
Task 1: It dawned on me pretty quickly that odd numbers wouldn’t satisfy the pattern, so I used Mod() to get rid of those, then simply split the string in half using the string length and compared the first half to the second half. Easy enough.
Task 2: Turns out my regex skills aren’t as creative as others. With the helpful hint that people were using Regex, I did some research and found a suitable solution to identify the Invalid ID’s.
An alternative that I considered was just splitting the string, which had a max value of 10 into separate streams and then rejoining them towards the end. The auspice of building out that many tools seemed like more work than exploring the Regex, so that’s the route I went in the end.
And now back to the breathing easy, waiting until Day 3. Cheers, -Jay
As @PhilipMannering famously said "RegEx is the sex"
@mceleavey
Great puzzle today! I will admit that I was very challenged by part 2, but in the end I learned a lot of new skills! Excited for the next challenge!
Ran into a myriad of issues no thanks to my reading comprehension and improper data types... Nonetheless a fun challenge.
Oh boy do I have a lot to say about this one so buckle in if you actually read these, its mind-dump time.First, treating RegEx as part of BaseA is something akin to pretending alcohol is not a drug: If it quacks like a duck it is probably a social construct created by a polite fiction of additional embedding.
So, no RegEx for me today, a stance which I will definitely reverse once things get hard.
That said, this is a neat problem to solve in Alteryx, as evidence by the attached file where I do Part 1 two different ways and Part 2 3x.
There are three parts to the problem(s)
1. Get the data into a usable form. Minimally, parse the ranges, maybe turn them into start/end or start/length pairs.
2. Find all the IDs to check.
3. Check them and throw out all the invalids (Hospital privatization joke removed.)
4. Profit. Also, sum things and consider duplicates.
Spoilery discussion of the First Pass, or how to solve it quickly.
The first pass through each is usually the bluntest. If I'm trying to get the thing done fast, I'm going to do each step in isolation and, where possible, just bash through problems. This is Part1 Initial and Part2 Ugly in the file. For Part 1 I just went through each text parsing step until I reached the end. Cut Start and End out of each range, create all the IDs from Start to End, Throw out the odd ones because why not minimally optimize, Split the remainder in half, compare left side to right side and keep the matches and you're done with part 1. Part 2, taken as a brute force problem, is really just part 2 done for every factor between 2 and Max(ID.Length). Once that showed itself to be 10, I just built the other 8 cases and bing (not Bing. Never Bing.) you have something you can sum into an answer after you make it not a string again because you forgot to do that like, every time.
I don't like stopping at the brute force solution so after checking in the time, back we go to put on our optimization hats.
Start by expanding the optimization from part1. Instead of odd lengths, we can throw out any combination of Length and UnitSize (the size of duplicated string) where Mod(Length, UnitSize) !=0. Can't find a pattern of 3 in a string of 8.
Then, instead of doing 10 different cases, we can treat every case as just having 10 substrings of length UnitSize, noting that we create a bunch of blanks when we exceed N=Length/UnitSize. That's fine. We can deal with blanks using the magic of cross tabulation.
Once we've Cross-Tabbed to leave only the non-empties, we can use Count Distinct and grouping to count the number of different patterns of length UnitSize for each ID & UnitSize combo. Count=1 implies a full pattern match, so we keep those, Unique on ID, because 1111 will be a match on both UnitSize=1 and UnitSize=2 and we have it. Cross tab, Filter, Summarize is a useful pattern to keep in your head for I've got this set of columns and I need to find the most/best/number of, etc. So that's good, but we can do better. Creating all 10 fields and having to Crosstab suggests we should be testing some other way.
Final (both parts) version or how to solve it pretty:
Enter the Replace function and the glory of the void (the part of the void will be played by IsEmpty())First half stays the same as all versions. Text to Columns the rows, generate rows twice. First one for the IDs, second one for the possible UnitSize combinations. Embedding the maximum unit size as Length/2 into the Generate rows saves us a step and some records. Records are the worst. Throw them out as soon as you can.
Note that we are no longer calculating Start or End, we're just inserting their definitions in the couple of places we use them. If you're making a workflow for reasonable people, do not do this thing. Put your variables in fields, name them things. This is not for reasonable people though; this is for the subset of maniacs inclined to do AoC. So we embed.
After creating all our possibilities, we test in a single filter tool. Same note as above, if this was for public consumption, define the thing in a formula and filter on the thing. Here however, we filter on IsEmpty(Replace(tostring([ID]),left(tostring([ID]),[UnitSize]), ""))
ToStrings because we just leave ID as a number all the way through instead of swapping to strings and back in the brute force version.
The filter gives us all the invalid IDs. From there, part 1 is just take the ones where UnitSize=Length/2 and Part 2 is, once again, taking the Unique values.
I wanted to use Regex_match but couldn't get it to work correctly. Instead, I took a brute-force approach by creating and checking every possible pattern. Reviewing other people's Regex solutions was very insightful.
Ah today was a breath of fresh air 😀
I tried with multiple Generate Rows tools for Part 2, and then learned RegEx solution from the Community. Thanks!
Already a break from macros on Day 2? Is this normal?
Ok looked through some of the other comments and learned that I've barely even scratched the surface on my regex journey! As I'm working on these, the "Make a man out of you" song from Disney's Mulan keeps playing in my head - but instead AoC will make a coder out of you (me?)....oh now that song's in your head too? You're welcome 😊
Day 2 was a little easier than day 1 but I went the long route to get the second part of the answer, regex was helpful but could have done it with complex left and right formulas too.
I felt Day 2 was easier than Day 1.