Solution to problem 4 in Python

This commit is contained in:
David Doblas Jiménez 2022-02-27 20:17:01 +01:00
parent 33889843c1
commit 5f17db1f8c

View File

@ -24,18 +24,23 @@
# What is the sum of the sector IDs of the real rooms?
from collections import Counter
from typing import Tuple
from typing import Tuple, Union
with open("files/P4.txt") as f:
instructions = [line for line in f.read().strip().split()]
def split_instruction(instr: str) -> Tuple[str, str, str]:
*name_, sector_id_checksum = str(instr).split("-")
name = "".join(name_)
def split_instruction(
instr: str, split_name: bool = True
) -> Union[Tuple[str, int, str], Tuple[list[str], int, str]]:
*name, sector_id_checksum = str(instr).split("-")
if split_name:
name_: str = "".join(name)
else:
name_: list[str] = name
sector_id, checksum = sector_id_checksum[:3], sector_id_checksum[4:-1]
return name, sector_id, checksum
return name_, int(sector_id), checksum
def part_1() -> None:
@ -46,10 +51,49 @@ def part_1() -> None:
chars = Counter(sorted(name))
checksum_calculated = "".join(n[0] for n in chars.most_common(5))
if checksum_calculated == checksum:
count += int(sector_id)
count += sector_id
print(f"The sum is {count}")
# --- Part Two ---
# With all the decoy data out of the way, it's time to decrypt this list and
# get moving.
# The room names are encrypted by a state-of-the-art shift cipher, which is
# nearly unbreakable without the right software. However, the information kiosk
# designers at Easter Bunny HQ were not expecting to deal with a master
# cryptographer like yourself.
# To decrypt a room name, rotate each letter forward through the alphabet a
# number of times equal to the room's sector ID. A becomes B, B becomes C, Z
# becomes A, and so on. Dashes become spaces.
# For example, the real name for qzmt-zixmtkozy-ivhz-343 is very encrypted
# name.
# What is the sector ID of the room where North Pole objects are stored?
def caeser_shift(string: str, rotation: int) -> str:
return "".join(
chr(((ord(char) - ord("a") + rotation) % 26) + ord("a"))
for char in string
)
def part_2() -> None:
for instruction in instructions:
name, sector_id, checksum = split_instruction(
instruction, split_name=False
)
_decrypted = [caeser_shift(string, sector_id % 26) for string in name]
decrypted: str = " ".join(["".join(word) for word in _decrypted])
if decrypted.startswith("northpole"):
print(f"The sector ID is {sector_id}")
if __name__ == "__main__":
part_1()
part_2()