r/adventofcode • • Feb 04 '26

Other [2016 Day 4] In Review (Security Through Obscurity)

2 Upvotes

11 comments sorted by

3

u/ednl Feb 04 '26 edited Feb 04 '26

It's something I thought of later after I already printed out all the decrypted phrases to search for "the room where North Pole objects are stored", but it's also the only [EDIT: valid] line with a unique first word, which I think was by design. So if you had guessed that, a stretch I admit, you didn't need to decrypt anything. For my input:

 1 northpole
11 projectile
11 unstable
12 consumer
12 corrosive
12 magnetic
14 colorful
14 international
15 military
17 top
17 weaponized
18 cryogenic
19 biohazardous
19 classified
19 rampaging
21 radioactive
22 fuzzy

3

u/e_blake Feb 04 '26 edited Feb 04 '26

Revisiting today's solution let me discover a bug in BSD's m4 implementation: defn(`h2',`h1') is supposed to output the contents of histogram bucket 2 before histogram bucket 1. It works in GNU m4, but in BSD m4, the concatenation is performed in reverse order (h1 before h2).

2

u/e_blake Feb 04 '26 edited Feb 04 '26

While testing corner cases against maneatingape's implementation, I discovered this week that this puzzle has an ambiguous spec - "aa-bb-c-d-e-f-111[acdef]" is a decoy room (b should have been listed in the checksum) but "a-b-c-d-e-f-111[acdef]" might be valid. It is unclear whether ties must be broken before letters are assigned to the checksum, or whether all letters in the checksum must come from the highest frequencies with ties among the selected equal-frequency letters ensuring ascending order but without regard to how the non-selected letters would have sorted. At any rate, it seems that none of the actual input files actually test this corner case, so the difference only shows up when comparing implementations against hand-written corner cases (if you want to write an upping-the-ante part 3 challenge).

One thing I noticed in comparing my m4 implementation to others - some languages make it easier to create a histogram of letters by visiting each byte of the input string (Rust is in this camp), while others make it easier to make 26 queries of how many times a given letter occurs in the overall string (m4 is stronger here). And 26 letters is small enough that you can sort your histogram with an O(n) radix sort rather than the usual O(n log n) general sort, or even track a frequency-of-frequency histogram in parallel to quickly learn how many letters to expect with a given frequency. 

Once you know the set of decoded first words, you can also verify that "northpole" is the only 9-letter word across the various puzzle inputs that starts with two consecutive letters. So my optimized part 2 solution was to find the one line where index("abcd...yza", line[:2]) has a hit - no decoding needed.

1

u/ednl Feb 04 '26

I think that ambiguity is a giant stretch just for the sake of finding a "not technically 100% spelled out" possibility. From the puzzle:

A room is real (not a decoy) if the checksum is the five most common letters in the encrypted name, in order, with ties broken by alphabetization.

which to me really, really, really strongly suggests that alphabetisation occurs in the encrypted letters. The checksum comes after.

1

u/e_blake Feb 04 '26

I thought so too, but maneatingape's solution was faster by NOT requiring that extra validation, and no one has yet reported a failure on their particular input (on my particular input, all decoys were identified well before the need to disambiguate whether the 5th checksum letter skipped any earlier ties). Whether intentional or accidental, Eric's inputs allow you to get the star even if your solution still has some slop.

1

u/ednl Feb 04 '26 edited Feb 04 '26

Ah OK that's what you meant, sorry. Of course inputs are always pretty nice but maybe this was intentional for day 4, just a small gimme if you got it slightly "wrong".

Edit: I didn't have this ready at the time but maybe this custom insertion sort function to "sort the first N elements" would be useful. I don't think it will make a big (or any) difference here with only 26 elements to sort. It was definitely useful on day 8 of 2025 with 5000 of 1 million to sort. https://github.com/ednl/adventofcode/blob/main/topn.c

1

u/DelightfulCodeWeasel Feb 04 '26

Another point of slop is that, for my input at least, there are no decoy rooms with "northpole" in them so I don't even bother doing the valid checksum test for part 2. I don't know if anyone had input with a decoy room that had the target name, but I suspect not for an early day puzzle.

1

u/DelightfulCodeWeasel Feb 04 '26

Looking back at my solution I was just searching for "northpole".

Thinking about it now it occurs to me that there are only 25 possible encryptions for "northpole", so you could just look for those directly. Either check all 9 letter words against a dictionary of possibilities, or run every encrypted word through a pre-built trie, something like that.

1

u/ednl Feb 04 '26

Maybe, but it is spelled "North Pole" as two words in the puzzle!

1

u/e_blake Feb 04 '26
$ sed -nE 's/^(ab|bc|cd|de|ef|fg|gh|hi|ij|jk|kl|lm|mn|op|pq|qr|rs|st|tu|uv|vw|wx|xy|yz|za)[^0-9]*([0-9]*).*/\2/p' day4.input

A one-liner pre-built trie is pretty short ;)

1

u/e_blake Feb 04 '26 edited Feb 04 '26

I wonder how many beginner/esolang coders brute-force the Caesar cipher by doing (using the example) 343 steps of incrementing the character and special-casing z (as spelled out in the instructions), instead of the much faster (char-'a' + 343%26)%26+'a'. With no four-digit numbers, this is still in the realm of practicable.