with open("input/day7.txt", "r") as f:
    inputLines = tuple(line.strip() for line in f)

import re

"""
Explanation: Day 7: Internet Protocol Version 7
End of explanation
"""


def isABBA(text):
    # Use a negative lookahead assertion to avoid matching four equal characters.
    return re.search(r"(.)(?!\1)(.)\2\1", text) is not None

assert     isABBA("abba")
assert     isABBA("xabba")
assert not isABBA("aaaa")
assert     isABBA("abcoxxoxyz")
assert     isABBA("aabba")
assert     isABBA("aaabba")
assert     isABBA("aaaabba")

def ipAddressSequences(ipAddress):
    # We use a pattern for the hypernet sequences for splitting.
    # Moreover, we capture the letters in the hypernet sequences, such that
    # normal and hypernet sequences will be alternating in the result.
    sequences = re.split(r"\[([^\]]+)\]", ipAddress)
    normalSequences = tuple(sequences[::2])
    hypernetSequences = tuple(sequences[1::2])
    return normalSequences, hypernetSequences
    
assert ipAddressSequences("abba[mnop]qrst") == (("abba", "qrst"), ("mnop",))
assert ipAddressSequences("abcd[bddb]xyyx") == (("abcd", "xyyx"), ("bddb",))
assert ipAddressSequences("aaaa[qwer]tyui") == (("aaaa", "tyui"), ("qwer",))
assert ipAddressSequences("ioxxoj[asdfgh]zxcvbn") == (("ioxxoj", "zxcvbn"), ("asdfgh",))
assert ipAddressSequences("a[b]") == (("a", ""), ("b",))
assert ipAddressSequences("[b]a") == (("", "a"), ("b",))
assert ipAddressSequences("[b]") == (("", ""), ("b",))

def supportsTLS(ipAddress):
    normal, hypernet = ipAddressSequences(ipAddress)
    return any(isABBA(s) for s in normal) and not any(isABBA(s) for s in hypernet)
    
assert     supportsTLS("abba[mnop]qrst")
assert not supportsTLS("abcd[bddb]xyyx")
assert not supportsTLS("aaaa[qwer]tyui")
assert     supportsTLS("ioxxoj[asdfgh]zxcvbn")

sum(1 for ipAddress in inputLines if supportsTLS(ipAddress))

"""
Explanation: Part 1: ABBA pattern in address, but not in hypernet sequences
End of explanation
"""


def supportsSSL(ipAddress):
    # The idea is that the ABA and the BAB patterns are separated by an odd number of brackets.
    return re.search(# first the ABA pattern
                       r"([a-z])(?!\1)([a-z])\1"
                     # then an arbitrary number of letters
                     + r"[a-z]*"
                     # then an opening or closing bracket
                     + r"[\[\]]"
                     # then any number of blocks which contain letters, a bracket, more letters, and another bracket
                     + r"([a-z]*[\[\]][a-z]*[\[\]]]*)*" 
                     # then an arbitrary number of letters
                     + r"[^\[\]]*"
                     # finally, the BAB pattern
                     + r"\2\1\2", 
                     ipAddress) is not None

assert     supportsSSL("aba[bab]xyz")
assert not supportsSSL("xyx[xyx]xyx")
assert     supportsSSL("aaa[kek]eke")
assert     supportsSSL("zazbz[bzb]cdb")

sum(1 for ipAddress in inputLines if supportsSSL(ipAddress))

"""
Explanation: Part 2: ABA and corresponding BAB pattern in normal and hypernet parts
End of explanation
"""


