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? # What is the sum of the sector IDs of the real rooms?
from collections import Counter from collections import Counter
from typing import Tuple from typing import Tuple, Union
with open("files/P4.txt") as f: with open("files/P4.txt") as f:
instructions = [line for line in f.read().strip().split()] instructions = [line for line in f.read().strip().split()]
def split_instruction(instr: str) -> Tuple[str, str, str]: def split_instruction(
*name_, sector_id_checksum = str(instr).split("-") instr: str, split_name: bool = True
name = "".join(name_) ) -> 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] 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: def part_1() -> None:
@ -46,10 +51,49 @@ def part_1() -> None:
chars = Counter(sorted(name)) chars = Counter(sorted(name))
checksum_calculated = "".join(n[0] for n in chars.most_common(5)) checksum_calculated = "".join(n[0] for n in chars.most_common(5))
if checksum_calculated == checksum: if checksum_calculated == checksum:
count += int(sector_id) count += sector_id
print(f"The sum is {count}") 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__": if __name__ == "__main__":
part_1() part_1()
part_2()