Advent Of Code

Advent Of Code 2015, Day 11: Getting Valid Passwords

Even Santa must change his password from time to time. Unfortunately, this time he needs our help because his new Security-Elf imposed some additional password requirements. A new password should be generated using Santa’s incremental method and then validated to ensure it is not breaking any safety rules.

Generating Passwords

The first step to get a new password is to convert the input into a list of ASCII codes. To increment the string, we use sv to evaluate the codes to base 27 and vs to revert the process. We also decrease the codes by 97 so we can use .Q.a to convert the ASCII codes to their respective letters.

{[x] .Q.a 27 vs 1+27 sv -97+"j"$x}

This works perfectly fine until you want to increment aaaaaaaa. Instead of aaaaaaab you get… b. Why? Decreasing ASCII codes by 97 means a becomes 0 so no matter how many a we have in our string, it will always be evaluated to 0. Thus, we are ending up with a b.

We can avoid this if we decrease the codes by 96 instead so a is 1, b is 2, and so on. However, z will not wrap around correctly to a anymore. To fix this, we add ” ” at the beginning of .Q.a and fill nulls with an a. We may still end up carrying over a letter (getting aa for z instead of a) so we use # to return a password of the same length as the input:

{[x] (neg count x)#"a"^(" ",.Q.a) 27 vs 1+27 sv -96+"j"$x}

Meeting The Requirements

Now it is time to validate our password. To be very pedantic, we check it contains exactly 8 lowercase letters:

if[any(8<>count x;not all within["j"$"x";(97;122)]);:0b];

However, it may not contain “i”, “o” or “l”:

if[any "iol" in x;:0b];

But it must include at least two different, non-overlapping pairs of letters, like aa, bb, or zz. So bbaceffg would meet this check but bbacebbg would not.

if[count[distinct x (-1 0)+/:where 0=deltas "j"$x]<2;:0b];

Using deltas and where we get the positions of consecutively repeating characters while adding (-1 0) gives us the preceding positions. We can now extract all pairs of letters and check that we have at least two different ones.

Finally, a valid password must also include one increasing straight of at least three letters, like abc, bcd etc. up to xyz. Combining next, scan, and # gives us all possible triplets. Thanks to deltas we get the difference between characters in each triplet and look for exactly one which, after dropping the first item, includes only 1s:

1=sum all each 1=1_/:deltas each 3#'next\[5;"j"$x]

Check out my github to see how to put it all together so you can also help Santa! After all, you don’t want to miss out on your Christmas gift this year!

Leave a comment