Solution to problem 12 in Python
This commit is contained in:
parent
69e541e250
commit
b34578de33
203
src/Year_2018/P12.py
Normal file
203
src/Year_2018/P12.py
Normal file
@ -0,0 +1,203 @@
|
||||
# --- Day 12: Subterranean Sustainability ---
|
||||
|
||||
# The year 518 is significantly more underground than your history books
|
||||
# implied. Either that, or you've arrived in a vast cavern network under the
|
||||
# North Pole.
|
||||
|
||||
# After exploring a little, you discover a long tunnel that contains a row of
|
||||
# small pots as far as you can see to your left and right. A few of them
|
||||
# contain plants - someone is trying to grow things in these
|
||||
# geothermally-heated caves.
|
||||
|
||||
# The pots are numbered, with 0 in front of you. To the left, the pots are
|
||||
# numbered -1, -2, -3, and so on; to the right, 1, 2, 3.... Your puzzle input
|
||||
# contains a list of pots from 0 to the right and whether they do (#) or do not
|
||||
# (.) currently contain a plant, the initial state. (No other pots currently
|
||||
# contain plants.) For example, an initial state of #..##.... indicates that
|
||||
# pots 0, 3, and 4 currently contain plants.
|
||||
|
||||
# Your puzzle input also contains some notes you find on a nearby table:
|
||||
# someone has been trying to figure out how these plants spread to nearby pots.
|
||||
# Based on the notes, for each generation of plants, a given pot has or does
|
||||
# not have a plant based on whether that pot (and the two pots on either side
|
||||
# of it) had a plant in the last generation. These are written as LLCRR => N,
|
||||
# where L are pots to the left, C is the current pot being considered, R are
|
||||
# the pots to the right, and N is whether the current pot will have a plant in
|
||||
# the next generation. For example:
|
||||
|
||||
# A note like ..#.. => . means that a pot that contains a plant but with no
|
||||
# plants within two pots of it will not have a plant in it during the next
|
||||
# generation.
|
||||
# A note like ##.## => . means that an empty pot with two plants on each
|
||||
# side of it will remain empty in the next generation.
|
||||
# A note like .##.# => # means that a pot has a plant in a given generation
|
||||
# if, in the previous generation, there were plants in that pot, the one
|
||||
# immediately to the left, and the one two pots to the right, but not in the
|
||||
# ones immediately to the right and two to the left.
|
||||
|
||||
# It's not clear what these plants are for, but you're sure it's important, so
|
||||
# you'd like to make sure the current configuration of plants is sustainable by
|
||||
# determining what will happen after 20 generations.
|
||||
|
||||
# For example, given the following input:
|
||||
|
||||
# initial state: #..#.#..##......###...###
|
||||
|
||||
# ...## => #
|
||||
# ..#.. => #
|
||||
# .#... => #
|
||||
# .#.#. => #
|
||||
# .#.## => #
|
||||
# .##.. => #
|
||||
# .#### => #
|
||||
# #.#.# => #
|
||||
# #.### => #
|
||||
# ##.#. => #
|
||||
# ##.## => #
|
||||
# ###.. => #
|
||||
# ###.# => #
|
||||
# ####. => #
|
||||
|
||||
# For brevity, in this example, only the combinations which do produce a plant
|
||||
# are listed. (Your input includes all possible combinations.) Then, the next
|
||||
# 20 generations will look like this:
|
||||
|
||||
# 1 2 3
|
||||
# 0 0 0 0
|
||||
# 0: ...#..#.#..##......###...###...........
|
||||
# 1: ...#...#....#.....#..#..#..#...........
|
||||
# 2: ...##..##...##....#..#..#..##..........
|
||||
# 3: ..#.#...#..#.#....#..#..#...#..........
|
||||
# 4: ...#.#..#...#.#...#..#..##..##.........
|
||||
# 5: ....#...##...#.#..#..#...#...#.........
|
||||
# 6: ....##.#.#....#...#..##..##..##........
|
||||
# 7: ...#..###.#...##..#...#...#...#........
|
||||
# 8: ...#....##.#.#.#..##..##..##..##.......
|
||||
# 9: ...##..#..#####....#...#...#...#.......
|
||||
# 10: ..#.#..#...#.##....##..##..##..##......
|
||||
# 11: ...#...##...#.#...#.#...#...#...#......
|
||||
# 12: ...##.#.#....#.#...#.#..##..##..##.....
|
||||
# 13: ..#..###.#....#.#...#....#...#...#.....
|
||||
# 14: ..#....##.#....#.#..##...##..##..##....
|
||||
# 15: ..##..#..#.#....#....#..#.#...#...#....
|
||||
# 16: .#.#..#...#.#...##...#...#.#..##..##...
|
||||
# 17: ..#...##...#.#.#.#...##...#....#...#...
|
||||
# 18: ..##.#.#....#####.#.#.#...##...##..##..
|
||||
# 19: .#..###.#..#.#.#######.#.#.#..#.#...#..
|
||||
# 20: .#....##....#####...#######....#.#..##.
|
||||
|
||||
# The generation is shown along the left, where 0 is the initial state. The pot
|
||||
# numbers are shown along the top, where 0 labels the center pot,
|
||||
# negative-numbered pots extend to the left, and positive pots extend toward
|
||||
# the right. Remember, the initial state begins at pot 0, which is not the
|
||||
# leftmost pot used in this example.
|
||||
|
||||
# After one generation, only seven plants remain. The one in pot 0 matched the
|
||||
# rule looking for ..#.., the one in pot 4 matched the rule looking for .#.#.,
|
||||
# pot 9 matched .##.., and so on.
|
||||
|
||||
# In this example, after 20 generations, the pots shown as # contain plants,
|
||||
# the furthest left of which is pot -2, and the furthest right of which is pot
|
||||
# 34. Adding up all the numbers of plant-containing pots after the 20th
|
||||
# generation produces 325.
|
||||
|
||||
# After 20 generations, what is the sum of the numbers of all pots which
|
||||
# contain a plant?
|
||||
|
||||
with open("files/P12.txt") as f:
|
||||
raw = [line for line in f.read().strip().split("\n")]
|
||||
|
||||
|
||||
def parse_data() -> tuple[str, dict[str, str]]:
|
||||
rules = {}
|
||||
for line in raw:
|
||||
if "initial state" in line:
|
||||
initial_state = line[15:]
|
||||
else:
|
||||
rules[line[:5]] = line[9:10]
|
||||
|
||||
return initial_state, rules
|
||||
|
||||
|
||||
def part_1() -> None:
|
||||
initial_state, rules = parse_data()
|
||||
current = dict(
|
||||
(idx, char) for idx, char in enumerate(initial_state) if char == "#"
|
||||
)
|
||||
_sum, difference = 0, {}
|
||||
for gen in range(20):
|
||||
# notes are given for a given pot plus two on each side
|
||||
left_side, right_side = min(current) - 2, max(current) + 2
|
||||
next_gen = {}
|
||||
for char in range(left_side, right_side + 1):
|
||||
pattern = ""
|
||||
for idx in range(char - 2, char + 3):
|
||||
if idx in current:
|
||||
pattern += current[idx]
|
||||
else:
|
||||
pattern += "."
|
||||
next_gen[char] = rules[pattern]
|
||||
current = dict(
|
||||
(idx, next_gen[idx]) for idx in next_gen if next_gen[idx] == "#"
|
||||
)
|
||||
diff = sum(current) - _sum
|
||||
if diff not in difference:
|
||||
difference[diff] = 1
|
||||
else:
|
||||
difference[diff] += 1
|
||||
_sum = sum(current)
|
||||
print(
|
||||
f"After 20 generations, there will be {sum(current)} pots containing plants"
|
||||
)
|
||||
|
||||
|
||||
# --- Part Two ---
|
||||
|
||||
# You realize that 20 generations aren't enough. After all, these plants will
|
||||
# need to last another 1500 years to even reach your timeline, not to mention
|
||||
# your future.
|
||||
|
||||
# After fifty billion (50000000000) generations, what is the sum of the numbers
|
||||
# of all pots which contain a plant?
|
||||
|
||||
|
||||
def part_2() -> None:
|
||||
generations = 50_000_000_000
|
||||
initial_state, rules = parse_data()
|
||||
current = dict(
|
||||
(idx, char) for idx, char in enumerate(initial_state) if char == "#"
|
||||
)
|
||||
_sum, difference = 0, {}
|
||||
for gen in range(generations):
|
||||
# notes are given for a given pot plus two on each side
|
||||
left_side, right_side = min(current) - 2, max(current) + 2
|
||||
next_gen = {}
|
||||
for char in range(left_side, right_side + 1):
|
||||
pattern = ""
|
||||
for idx in range(char - 2, char + 3):
|
||||
if idx in current:
|
||||
pattern += current[idx]
|
||||
else:
|
||||
pattern += "."
|
||||
next_gen[char] = rules[pattern]
|
||||
current = dict(
|
||||
(idx, next_gen[idx]) for idx in next_gen if next_gen[idx] == "#"
|
||||
)
|
||||
diff = sum(current) - _sum
|
||||
if diff not in difference:
|
||||
difference[diff] = 1
|
||||
else:
|
||||
difference[diff] += 1
|
||||
_sum = sum(current)
|
||||
# it is a periodic result, so skip most of the calculations
|
||||
if diff in difference and difference[diff] > 1000:
|
||||
res = sum(current) + (generations - gen - 1) * diff
|
||||
print(
|
||||
f"After 5e10 generations, there will be {res} pots containing plants"
|
||||
)
|
||||
break
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
part_1()
|
||||
part_2()
|
Loading…
Reference in New Issue
Block a user