Solution to problem 13 in Python

This commit is contained in:
David Doblas Jiménez 2022-08-14 16:47:31 +02:00
parent 1d0137c0e8
commit a38def1920
1 changed files with 123 additions and 0 deletions

123
src/Year_2015/P13.py Normal file
View File

@ -0,0 +1,123 @@
# --- Day 13: Knights of the Dinner Table ---
# In years past, the holiday feast with your family hasn't gone so well. Not
# everyone gets along! This year, you resolve, will be different. You're going
# to find the optimal seating arrangement and avoid all those awkward
# conversations.
# You start by writing up a list of everyone invited and the amount their
# happiness would increase or decrease if they were to find themselves sitting
# next to each other person. You have a circular table that will be just big
# enough to fit everyone comfortably, and so each person will have exactly two
# neighbors.
# For example, suppose you have only four attendees planned, and you calculate
# their potential happiness as follows:
# Alice would gain 54 happiness units by sitting next to Bob.
# Alice would lose 79 happiness units by sitting next to Carol.
# Alice would lose 2 happiness units by sitting next to David.
# Bob would gain 83 happiness units by sitting next to Alice.
# Bob would lose 7 happiness units by sitting next to Carol.
# Bob would lose 63 happiness units by sitting next to David.
# Carol would lose 62 happiness units by sitting next to Alice.
# Carol would gain 60 happiness units by sitting next to Bob.
# Carol would gain 55 happiness units by sitting next to David.
# David would gain 46 happiness units by sitting next to Alice.
# David would lose 7 happiness units by sitting next to Bob.
# David would gain 41 happiness units by sitting next to Carol.
# Then, if you seat Alice next to David, Alice would lose 2 happiness units
# (because David talks so much), but David would gain 46 happiness units
# (because Alice is such a good listener), for a total change of 44.
# If you continue around the table, you could then seat Bob next to Alice (Bob
# gains 83, Alice gains 54). Finally, seat Carol, who sits next to Bob (Carol
# gains 60, Bob loses 7) and David (Carol gains 55, David gains 41). The
# arrangement looks like this:
# +41 +46
# +55 David -2
# Carol Alice
# +60 Bob +54
# -7 +83
# After trying every other seating arrangement in this hypothetical scenario,
# you find that this one is the most optimal, with a total change in happiness
# of 330.
# What is the total change in happiness for the optimal seating arrangement of
# the actual guest list?
import re
from collections import defaultdict
from itertools import permutations
from typing import DefaultDict
with open("files/P13.txt") as f:
sittings = [line for line in f.read().strip().split("\n")]
arrengements: DefaultDict = defaultdict(dict)
for happiness in sittings:
pattern = r"(?P<p1>\S+) would (?P<op>lose|gain) (?P<val>\d+) happiness units by sitting next to (?P<p2>\S+)."
matches = re.match(pattern, happiness)
p1, op, val, p2 = re.match(pattern, happiness).group(
"p1", "op", "val", "p2"
)
arrengements[p1][p2] = -int(val) if op == "lose" else int(val)
def part_1() -> None:
max_happiness = 0
for ordering in permutations(arrengements.keys()):
happiness = sum(
arrengements[a][b] + arrengements[b][a]
for a, b in zip(ordering, ordering[1:])
)
happiness += (
arrengements[ordering[0]][ordering[-1]]
+ arrengements[ordering[-1]][ordering[0]]
)
max_happiness = max(max_happiness, happiness)
print(f"The total change in happiness is {max_happiness}")
# --- Part Two ---
# In all the commotion, you realize that you forgot to seat yourself. At this
# point, you're pretty apathetic toward the whole thing, and your happiness
# wouldn't really go up or down regardless of who you sit next to. You assume
# everyone else would be just as ambivalent about sitting next to you, too.
# So, add yourself to the list, and give all happiness relationships that
# involve you a score of 0.
# What is the total change in happiness for the optimal seating arrangement
# that actually includes yourself?
def part_2() -> None:
for somebody in list(arrengements.keys()):
arrengements["me"][somebody] = 0
arrengements[somebody]["me"] = 0
max_happiness = 0
for ordering in permutations(arrengements.keys()):
happiness = sum(
arrengements[a][b] + arrengements[b][a]
for a, b in zip(ordering, ordering[1:])
)
happiness += (
arrengements[ordering[0]][ordering[-1]]
+ arrengements[ordering[-1]][ordering[0]]
)
max_happiness = max(max_happiness, happiness)
print(
f"The total change in happiness is {max_happiness}, including myself"
)
if __name__ == "__main__":
part_1()
part_2()