Solution to problem 14 in Python
This commit is contained in:
parent
f8f963b973
commit
121f63f2d7
146
src/Year_2021/P14.py
Normal file
146
src/Year_2021/P14.py
Normal file
@ -0,0 +1,146 @@
|
||||
# --- Day 14: Extended Polymerization ---
|
||||
|
||||
# The incredible pressures at this depth are starting to put a strain on your
|
||||
# submarine. The submarine has polymerization equipment that would produce
|
||||
# suitable materials to reinforce the submarine, and the nearby
|
||||
# volcanically-active caves should even have the necessary input elements in
|
||||
# sufficient quantities.
|
||||
|
||||
# The submarine manual contains instructions for finding the optimal polymer
|
||||
# formula; specifically, it offers a polymer template and a list of pair
|
||||
# insertion rules (your puzzle input). You just need to work out what polymer
|
||||
# would result after repeating the pair insertion process a few times.
|
||||
|
||||
# For example:
|
||||
|
||||
# NNCB
|
||||
|
||||
# CH -> B
|
||||
# HH -> N
|
||||
# CB -> H
|
||||
# NH -> C
|
||||
# HB -> C
|
||||
# HC -> B
|
||||
# HN -> C
|
||||
# NN -> C
|
||||
# BH -> H
|
||||
# NC -> B
|
||||
# NB -> B
|
||||
# BN -> B
|
||||
# BB -> N
|
||||
# BC -> B
|
||||
# CC -> N
|
||||
# CN -> C
|
||||
|
||||
# The first line is the polymer template - this is the starting point of the
|
||||
# process.
|
||||
|
||||
# The following section defines the pair insertion rules. A rule like AB -> C
|
||||
# means that when elements A and B are immediately adjacent, element C should be
|
||||
# inserted between them. These insertions all happen simultaneously.
|
||||
|
||||
# So, starting with the polymer template NNCB, the first step simultaneously
|
||||
# considers all three pairs:
|
||||
|
||||
# The first pair (NN) matches the rule NN -> C, so element C is inserted
|
||||
# between the first N and the second N.
|
||||
# The second pair (NC) matches the rule NC -> B, so element B is inserted
|
||||
# between the N and the C.
|
||||
# The third pair (CB) matches the rule CB -> H, so element H is inserted
|
||||
# between the C and the B.
|
||||
|
||||
# Note that these pairs overlap: the second element of one pair is the first
|
||||
# element of the next pair. Also, because all pairs are considered
|
||||
# simultaneously, inserted elements are not considered to be part of a pair
|
||||
# until the next step.
|
||||
|
||||
# After the first step of this process, the polymer becomes NCNBCHB.
|
||||
|
||||
# Here are the results of a few steps using the above rules:
|
||||
|
||||
# Template: NNCB
|
||||
# After step 1: NCNBCHB
|
||||
# After step 2: NBCCNBBBCBHCB
|
||||
# After step 3: NBBBCNCCNBBNBNBBCHBHHBCHB
|
||||
# After step 4: NBBNBNBBCCNBCNCCNBBNBBNBBBNBBNBBCBHCBHHNHCBBCBHCB
|
||||
|
||||
# This polymer grows quickly. After step 5, it has length 97; After step 10, it
|
||||
# has length 3073. After step 10, B occurs 1749 times, C occurs 298 times, H
|
||||
# occurs 161 times, and N occurs 865 times; taking the quantity of the most
|
||||
# common element (B, 1749) and subtracting the quantity of the least common
|
||||
# element (H, 161) produces 1749 - 161 = 1588.
|
||||
|
||||
# Apply 10 steps of pair insertion to the polymer template and find the most and
|
||||
# least common elements in the result. What do you get if you take the quantity
|
||||
# of the most common element and subtract the quantity of the least common
|
||||
# element?
|
||||
|
||||
from collections import Counter
|
||||
|
||||
|
||||
def part_1() -> None:
|
||||
polymer, polymer_rules = open("files/P14.txt").read().split("\n\n")
|
||||
rules = {
|
||||
s: e
|
||||
for line in polymer_rules.strip().split("\n")
|
||||
for s, e in [line.strip().split(" -> ")]
|
||||
}
|
||||
|
||||
for _ in range(10):
|
||||
polymer = polymer[0] + "".join(
|
||||
rules[a + b] + b for a, b in zip(polymer, polymer[1:])
|
||||
)
|
||||
|
||||
most_common = Counter(polymer).most_common()
|
||||
print(f"The result is {most_common[0][1] - most_common[-1][1]}")
|
||||
|
||||
|
||||
# --- Part Two ---
|
||||
|
||||
# The resulting polymer isn't nearly strong enough to reinforce the submarine.
|
||||
# You'll need to run more steps of the pair insertion process; a total of 40
|
||||
# steps should do it.
|
||||
|
||||
# In the above example, the most common element is B (occurring 2192039569602
|
||||
# times) and the least common element is H (occurring 3849876073 times);
|
||||
# subtracting these produces 2188189693529.
|
||||
|
||||
# Apply 40 steps of pair insertion to the polymer template and find the most
|
||||
# and least common elements in the result. What do you get if you take the
|
||||
# quantity of the most common element and subtract the quantity of the least
|
||||
# common element?
|
||||
|
||||
from collections import defaultdict # noqa: E402
|
||||
|
||||
|
||||
def part_2() -> None:
|
||||
polymer, polymer_rules = open("files/P14.txt").read().split("\n\n")
|
||||
rules = {
|
||||
s: e
|
||||
for line in polymer_rules.strip().split("\n")
|
||||
for s, e in [line.strip().split(" -> ")]
|
||||
}
|
||||
counts = {key: polymer.count(key) for key in rules}
|
||||
|
||||
for _ in range(40):
|
||||
new_counts = defaultdict(int)
|
||||
|
||||
for pair, count in counts.items():
|
||||
char = rules[pair]
|
||||
new_counts[pair[0] + char] += count
|
||||
new_counts[char + pair[1]] += count
|
||||
|
||||
counts = new_counts
|
||||
|
||||
element_counts = defaultdict(int, {polymer[0]: 1})
|
||||
|
||||
for pair, count in counts.items():
|
||||
element_counts[pair[1]] += count
|
||||
|
||||
most_common = Counter(element_counts).most_common()
|
||||
print(f"The result is {most_common[0][1] - most_common[-1][1]}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
part_1()
|
||||
part_2()
|
Loading…
Reference in New Issue
Block a user