AoC 2016 Day 7: IPv7 Support Counter

Source: Internet Protocol Version 7

Part 1: The input is a list of strings, potentially containing sequences in square brackets. Find all strings that have an ABBA sequence (two characters followed by the same two in reverse order) outside of any square brackets, but no ABBA sequences in square brackets.

I know regular expressions

re_abba = re.compile(r'([a-z])((?!\1)[a-z])\2\1')

tls_valid = 0

with open(args.input, 'r') as fin:
    for line in fin:
        line = line.strip('\n')

        hypernet_list = []
        def store_and_replace(m):
            hypernet_list.append(m.group(0))
            return '--'

        supernet = re.sub(r'\[[a-z]+\]', store_and_replace, line)
        hypernet = '--'.join(hypernet_list)

        tls = ssl = False

        if re_abba.search(supernet) and not re_abba.search(hypernet):
            tls_valid += 1

print(tls_valid)

What I’m doing is first extracting characters in square brackets into a list (hypernet_list), replacing them with a string that won’t match an ABBA pattern: --. Then I combine that list into a similar looking string. Then I apply the ABBA regex to both, checking for my condition. Let’s look at that regex though:

([a-z])((?!\1)[a-z])\2\1

To break that down, we have three parts:

([a-z])       # First, match any character
((?!\1)[a-z]) # Then, match any character, but not the same one as the first group
\2\1          # Match the first two characters again in reverse order

The interesting part is the negative lookhead in the second group. It says, no matter what you match, it can’t be this (this in this case being the first group \1). A bit complicated, but to my eyes at least, exactly the right tool for the job.

Part 2: Count strings that have an ABA sequence outside of a bracketed section and a matching BAB section inside.

Finding ABA sequences isn’t much harder, but you have to make sure that they can overlap (re.findall(..., overlapped = True)):

re_aba = re.compile(r'([a-z])((?!\1)[a-z])\1')

ssl_valid = 0

with open(args.input, 'r') as fin:
    for line in fin:
        # ...

        ssl = False

        for (a, b) in re_aba.findall(supernet, overlapped = True):
            if b + a + b in hypernet:
                ssl = True

        if ssl: ssl_valid += 1

print(ssl_valid)

An interesting problem.