Solution to problem 5 in Python

This commit is contained in:
David Doblas Jiménez 2022-03-02 21:24:22 +01:00
parent b7d0679c45
commit 6b8e82ed78

123
src/Year_2018/P5.py Normal file
View File

@ -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()