Close

Advent of Code 2025 – Day 2

Gift Shop

Day 2 was both easy and hard. Easy because it was easy to understand and hard because I knew there was a trick that would make an efficient solution for part 2 but I couldn’t remember it.

For part 1, I just divide the line of ranges into rows and then use regexp to pull the low and high value for each range. I could have used a macro or recursive CTE to generate the values for every number in each of the ranges; but I already had a pl/sql function I’ve used in the past handy called simply “integers” that would return a table of all integers from A-to-B. I did have to make one small adjustment because the original used FOR loops which have a 32-bit PLS_INTEGER limit on the indexes, so for ranges across large numbers I used a while loop to iterate. I put a copy of the function in git here.
Now that I have all of the numbers for each range, I split them in half to see if they are composed of a duplicate substring. If the first half matches the second half, then return that number, otherwise the case returns NULL.
Then sum the results.

WITH data
    AS
        (SELECT a, b, COLUMN_VALUE n
           FROM (SELECT TO_NUMBER(REGEXP_SUBSTR(x.COLUMN_VALUE, '[^-]+')) a,
                        TO_NUMBER(REGEXP_SUBSTR(x.COLUMN_VALUE, '[^-]+$')) b
                   FROM advent.data2rows('advent2025-2sample') CROSS APPLY str2tbl(str, ',') x)
                CROSS APPLY integers(a, b))
SELECT SUM(x)
  FROM (SELECT d.*,
               CASE
                   WHEN SUBSTR(TO_CHAR(n), 1, FLOOR(LENGTH(TO_CHAR(n)) / 2)) =
                        SUBSTR(TO_CHAR(n), FLOOR(LENGTH(TO_CHAR(n)) / 2) + 1)
                   THEN
                       n
               END x
          FROM data d);

As I mentioned above I struggled on part 2. I knew I couldn’t use the same simple strategy as in part 1. Or rather, I could but I knew I didn’t want to because it would be very complicated and would scale poorly. So I took a break, did some chores and shopping and while I was gone I remembered something I learned a long time ago, I’m not sure where, maybe one of my Knuth books or something from college, or maybe even some other puzzle. A simple trick to finding if a string is constructed from repeated substrings is to double it and then search for that original string within the doubled string. But – you don’t use the first or last characters of that new string. If you find your string in that new string, then it must be composed entirely of duplicate substrings. If not, then it’s not.

For example, if my string is ABCDABCD. Then doubled with the first and last removed is BCDABCDABCDABC. With than superstring we can still find the original string highlighted there in the middle. It will work with more than one duplication too. If my string is ABCABCABC, then the super-string is BCABCABCABCABCAB, but again, we can find the original string inside so we know it’s composed of duplicated substrings. It works because the duplicates will follow the same pattern when concatenated to themselves. So the 2nd and following instances of the substring will pair up with the first instance of the substring in the concatenation thus recreating the original string.

Compare that to a string that is not constructed of duplicate substrings, e.g. ABABABXAB. The super string is BABABXABABABABXA and nowhere in there can we find the original string. Since the pattern isn’t duplicated in the original, concatenating it won’t recreate the pattern.

WITH data
    AS
        (SELECT a, b, TO_CHAR(COLUMN_VALUE) n
           FROM (SELECT TO_NUMBER(REGEXP_SUBSTR(x.COLUMN_VALUE, '[^-]+')) a,
                        TO_NUMBER(REGEXP_SUBSTR(x.COLUMN_VALUE, '[^-]+$')) b
                   FROM advent.data2rows('advent2025-2sample') CROSS APPLY str2tbl(str, ',') x)
                CROSS APPLY integers(a, b))
select sum(to_number(n)) from
(SELECT d.*, INSTR(SUBSTR(n || n, 2, LENGTH(n) * 2 - 2), n) x
  FROM data d)
  where x != 0;

That was fun. Not only did I start a few days late, I was also slow in getting it. But I’m glad I finally remembered how the concatenating thing worked.

Leave a Reply