diff --git a/pyproject.toml b/pyproject.toml index 0c35c2b..07df662 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,11 @@ force_grid_wrap = 0 use_parentheses = true line_length = 79 +[tool.mypy] +pretty = true +show_traceback = true +allow_redefinition = true + [tool.black] line-length = 79 target-version = ['py38'] @@ -53,8 +58,3 @@ exclude = ''' # the root of the project ) ''' - -[tool.mypy] -pretty = true -show-traceback = true -allow-redefinition = true diff --git a/src/Year_2019/P6.py b/src/Year_2019/P6.py index 2dc12fd..10ff87b 100644 --- a/src/Year_2019/P6.py +++ b/src/Year_2019/P6.py @@ -70,6 +70,7 @@ from collections import defaultdict +from typing import Dict, List, Optional with open("files/P6.txt") as f: orbits = [line for line in f.read().strip().split()] @@ -90,8 +91,105 @@ def part_1(): total_orbits = count_orbits(universe, "COM", 0, 0) - print(f"There are {total_orbits} in our universe") + print(f"There are {total_orbits} orbits in our universe") + + +# --- Part Two --- + +# Now, you just need to figure out how many orbital transfers you (YOU) need to\ +# take to get to Santa (SAN). + +# You start at the object YOU are orbiting; your destination is the object SAN +# is orbiting. An orbital transfer lets you move from any object to an object +# orbiting or orbited by that object. + +# For example, suppose you have the following map: + +# COM)B +# B)C +# C)D +# D)E +# E)F +# B)G +# G)H +# D)I +# E)J +# J)K +# K)L +# K)YOU +# I)SAN + +# Visually, the above map of orbits looks like this: + +# YOU +# / +# G - H J - K - L +# / / +# COM - B - C - D - E - F +# \ +# I - SAN + +# In this example, YOU are in orbit around K, and SAN is in orbit around I. +# To move from K to I, a minimum of 4 orbital transfers are required: + +# K to J +# J to E +# E to D +# D to I + +# Afterward, the map of orbits looks like this: + +# G - H J - K - L +# / / +# COM - B - C - D - E - F +# \ +# I - SAN +# \ +# YOU + +# What is the minimum number of orbital transfers required to move from the +# object YOU are orbiting to the object SAN is orbiting? (Between the objects +# they are orbiting - not between YOU and SAN.) + + +def get_all_orbits(node: str, universe: Dict[str, str]) -> List[str]: + orbits = [] + while node in universe: + node = universe[node] + orbits.append(node) + return orbits + + +def common_orbit(node_a: List[str], node_b: List[str]) -> Optional[str]: + for orbit in node_a: + if orbit in node_b: + return orbit + return None + + +def distance_from(node_a: List[str], node_b: Optional[str]) -> int: + transfers = 0 + for v in node_a: + if v == node_b: + return transfers + transfers += 1 + return transfers + + +def part_2() -> None: + universe = {} + for orbit in orbits: + planet, satellite = orbit.split(")") + universe[satellite] = planet + + you = get_all_orbits("YOU", universe) + san = get_all_orbits("SAN", universe) + _common = common_orbit(you, san) + transfers = distance_from(you, _common) + distance_from(san, _common) + + print(f"There will be at least {transfers} orbital transfers") if __name__ == "__main__": part_1() + part_2()