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…
x
Reference in New Issue
Block a user