diff --git a/src/Year_2018/P5.py b/src/Year_2018/P5.py new file mode 100644 index 0000000..dc4344c --- /dev/null +++ b/src/Year_2018/P5.py @@ -0,0 +1,123 @@ +# --- Day 5: Alchemical Reduction --- + +# You've managed to sneak in to the prototype suit manufacturing lab. The Elves +# are making decent progress, but are still struggling with the suit's size +# reduction capabilities. + +# While the very latest in 1518 alchemical technology might have solved their +# problem eventually, you can do better. You scan the chemical composition of +# the suit's material and discover that it is formed by extremely long polymers +# (one of which is available as your puzzle input). + +# The polymer is formed by smaller units which, when triggered, react with each +# other such that two adjacent units of the same type and opposite polarity are +# destroyed. Units' types are represented by letters; units' polarity is +# represented by capitalization. For instance, r and R are units with the same +# type but opposite polarity, whereas r and s are entirely different types and +# do not react. + +# For example: + +# In aA, a and A react, leaving nothing behind. +# In abBA, bB destroys itself, leaving aA. As above, this then destroys +# itself, leaving nothing. +# In abAB, no two adjacent units are of the same type, and so nothing +# happens. +# In aabAAB, even though aa and AA are of the same type, their polarities +# match, and so nothing happens. + +# Now, consider a larger example, dabAcCaCBAcCcaDA: + +# dabAcCaCBAcCcaDA The first 'cC' is removed. +# dabAaCBAcCcaDA This creates 'Aa', which is removed. +# dabCBAcCcaDA Either 'cC' or 'Cc' are removed (the result is the same). +# dabCBAcaDA No further actions can be taken. + +# After all possible reactions, the resulting polymer contains 10 units. + +# How many units remain after fully reacting the polymer you scanned? (Note: +# in this puzzle and others, the input is large; if you copy/paste your input, +# make sure you get the whole thing.) + +import re +from copy import copy +from string import ascii_lowercase + +with open("files/P5.txt") as f: + polymer = [line for line in f.read().split()][0] + + +def react(s: str) -> bool: + return abs(ord(s[0]) - ord(s[1])) == 32 + + +def remove_substring(substr: str, s: str) -> str: + return re.sub(substr, "", s) + + +def part_1() -> None: + sequence = copy(polymer) + idx = 0 + while True: + try: + pair = "".join((sequence[idx], sequence[idx + 1])) + if react(pair): + sequence = remove_substring(pair, sequence) + idx = 0 + else: + idx += 1 + except IndexError: + break + print(f"There are {len(sequence)} units remaining") + + +# --- Part Two --- + +# Time to improve the polymer. + +# One of the unit types is causing problems; it's preventing the polymer from +# collapsing as much as it should. Your goal is to figure out which unit type +# is causing the most problems, remove all instances of it (regardless of +# polarity), fully react the remaining polymer, and measure its length. + +# For example, again using the polymer dabAcCaCBAcCcaDA from above: + +# Removing all A/a units produces dbcCCBcCcD. Fully reacting this polymer +# produces dbCBcD, which has length 6. +# Removing all B/b units produces daAcCaCAcCcaDA. Fully reacting this +# polymer produces daCAcaDA, which has length 8. +# Removing all C/c units produces dabAaBAaDA. Fully reacting this polymer +# produces daDA, which has length 4. +# Removing all D/d units produces abAcCaCBAcCcaA. Fully reacting this +# polymer produces abCBAc, which has length 6. + +# In this example, removing all C/c units was best, producing the answer 4. + +# What is the length of the shortest polymer you can produce by removing all +# units of exactly one type and fully reacting the result? + + +def part_2() -> None: + lengths = [] + for char in ascii_lowercase: + sequence = copy(polymer) + sequence = sequence.replace(char, "").replace(char.upper(), "") + idx = 0 + while True: + try: + pair = "".join((sequence[idx], sequence[idx + 1])) + if react(pair): + sequence = remove_substring(pair, sequence) + idx = 0 + else: + idx += 1 + except IndexError: + break + lengths.append(len(sequence)) + + print(f"The length of the shortest polymer is {min(lengths)}") + + +if __name__ == "__main__": + part_1() + part_2()