from collections import Counter from tools.aoc import AOCDay from typing import Any, Counter class Day(AOCDay): inputs = [ [ (1514, "input4_test"), (173787, "input4"), ], [ (548, "input4"), ], ] def get_valid_rooms(self) -> list[tuple[str, int]]: rooms = [] for line in self.getInput(): room_name_id, common = line[:-1].split("[") room_parts = room_name_id.split("-") room_id = int(room_parts[-1]) room_chars = Counter("".join(room_parts[:-1])) top_chars = "" top_count = max(room_chars.values()) for char, count in sorted(room_chars.items(), key=lambda k: (top_count - k[1], k)): if len(top_chars) < 5: top_chars += char top_count = count continue if count < top_count or len(top_chars) == 5: break top_chars += char if all(x in top_chars for x in common): rooms.append((" ".join(room_parts[:-1]), room_id)) return rooms def part1(self) -> Any: return sum([x[1] for x in self.get_valid_rooms()]) def part2(self) -> Any: for room_name, room_id in self.get_valid_rooms(): rot_room_name = "" for c in [ord(x) for x in room_name]: if c != 32: c = (c + room_id + 7) % 26 + 97 rot_room_name += chr(c) if "north" in rot_room_name and "pole" in rot_room_name and "object" in rot_room_name: return room_id if __name__ == "__main__": day = Day(2016, 4) day.run(verbose=True)