return SolverDay22._count_score(d2), False if not d2: return SolverDay22._count_score(d1), True as_tuple = (tuple(d1), tuple(d2)) if as_tuple in seen: return SolverDay22._count_score(d1), True seen.add(as_tuple) c1, c2 = d1.popleft(), d2.popleft() if len(d1) < c1 or len(d2) < c2: p1_winner = c1 > c2 else: _, p1_winner = SolverDay22._recursive_combat( deque(islice(d1, 0, c1)), deque(islice(d2, 0, c2))) if p1_winner: d1.extend([c1, c2]) else: d2.extend([c2, c1]) def part2(self) -> int: d1, d2 = self.puzzle.data return SolverDay22._recursive_combat(d1, d2)[0] if __name__ == '__main__': SolverDay22( PuzzleDownloader(day=22, parser=SolverDay22.parser).get_puzzle()).run()
dimensions = (len(cells[0]) // 2, len(cells) // 2, 0, 0) active = set() for y in range(len(cells)): for x in range(len(cells[0])): if cells[y][x] == "#": active.add( (x - len(cells[0]) // 2, y - len(cells) // 2, 0, 0)) return SmarterMultiverse(active_cells=active, dimensions=dimensions) def part1(self) -> int: u = BoringVerse(active_cells=self.puzzle.data.active_cells, dimensions=self.puzzle.data.dimensions) for _ in range(6): # should fix it so that .run_cycle return self.type, but... u = u.run_cycle() # type: ignore return len(u.active_cells) def part2(self) -> int: mu = self.puzzle.data for _ in range(6): mu = mu.run_cycle() return len(mu.active_cells) if __name__ == '__main__': SolverDay17( PuzzleDownloader(day=17, parser=SolverDay17.parser).get_puzzle()).run()
from aoc2020.shared.models import NoResultFoundException from aoc2020.shared.puzzle import Puzzle, PuzzleDownloader from aoc2020.shared.solver import Solver @dataclass class SolverDay1(Solver): puzzle: Puzzle[List[int]] TARGET: ClassVar[int] = 2020 def _solve_for(self, n: int) -> int: for x in combinations(self.puzzle.data, n): if sum(x) == self.TARGET: return prod(x) else: raise NoResultFoundException def part1(self) -> int: return self._solve_for(2) def part2(self) -> int: return self._solve_for(3) def parser(string: str) -> List[int]: return list(map(int, string.splitlines())) if __name__ == '__main__': SolverDay1(PuzzleDownloader(day=1, parser=parser).get_puzzle()).run()
@groupwise_parser def parser(group: Iterable[str]) -> Union[ValidationError, Passport]: single_line = " ".join(group) fields_as_str = single_line.split(" ") as_dict = {tuple(s.split(":")) for s in fields_as_str} try: return Passport.parse_obj(as_dict) except ValidationError as v: return v def part1(self) -> int: count = 0 for maybe_passport in self.puzzle.data: if isinstance(maybe_passport, Passport): count += 1 # part 1 doesn't care about anything but the correct fields being there (ie the MissingError) elif all([not isinstance(err.exc, MissingError) for err in maybe_passport.raw_errors]): # type: ignore count += 1 return count def part2(self) -> int: count = 0 for maybe_passport in self.puzzle.data: if isinstance(maybe_passport, Passport): count += 1 return count if __name__ == '__main__': SolverDay4(PuzzleDownloader(day=4, parser=SolverDay4.parser).get_puzzle()).run()
parser = Lark("\n".join(named_rules), start="r0") ok_count = 0 for line in self.puzzle.data[1].splitlines(): try: parser.parse(line) ok_count += 1 except LarkError: pass return ok_count def part1(self) -> int: return self._count_ok(self.puzzle.data[0].splitlines()) def part2(self) -> int: input_rules = [] for rule in self.puzzle.data[0].splitlines(): if not (rule.startswith("8:") or rule.startswith("11:")): input_rules.append(rule) new_rules_str = """\ 8: 42 | 42 8 11: 42 31 | 42 11 31""" new_rules = dedent(new_rules_str).splitlines() rules = input_rules + new_rules return self._count_ok(rules) if __name__ == '__main__': SolverDay19(PuzzleDownloader(day=19, parser=SolverDay19.parser).get_puzzle()).run()
puzzle: Puzzle _divider = 20201227 def _transformations(self, subject_number: int) -> Iterator[Tuple[int, int]]: """Yields the loop number and the its associated value""" value = 1 loop = 0 while True: value *= subject_number value %= self._divider yield loop, value loop += 1 @staticmethod def parser(input_: str) -> Tuple[CardPK, DoorPK]: card, door = input_.splitlines() return int(card), int(door) def part1(self) -> int: card_pk, door_pk = self.puzzle.data for loop, value in self._transformations(7): if value == card_pk: return next(islice(self._transformations(door_pk), loop, loop + 1))[1] if value == door_pk: return next(islice(self._transformations(card_pk), loop, loop + 1))[1] raise ValueError # should be unreachable if __name__ == '__main__': SolverDay25(PuzzleDownloader(day=25, parser=SolverDay25.parser).get_puzzle()).run()
**self.puzzle.data[index].dict(by_alias=True), "code": new_instruction_cls.__name__.lower() } new_instruction_set[index] = new_instruction_cls.parse_obj( new_instruction) return new_instruction_set def part2(self) -> int: for index, instruction in enumerate(self.puzzle.data): if instruction.code == "acc": continue elif instruction.code == "jmp": new_instruction_set = self._mutate_instruction(index, Nop) elif instruction.code == "nop": new_instruction_set = self._mutate_instruction(index, Jmp) else: assert_never(instruction.code) interpreter = Interpreter(new_instruction_set) try: return interpreter.run() except LoopDetected: pass raise NoResultFoundException if __name__ == '__main__': SolverDay8(PuzzleDownloader(day=8, parser=SolverDay8.parser).get_puzzle()).run()
return sum(map(lambda l: l.count("#"), s)) - len(monster_zones) @staticmethod def _monster_shape() -> List[Tuple[int, int]]: s = """\ # # ## ## ### # # # # # # """ res = [] for y, row in enumerate(s.splitlines()): for x, cell in enumerate(row): if cell == "#": res.append((x, y)) return res @staticmethod def _detect_monster(image: List[str], xx: int, yy: int) -> Optional[Set[Tuple[int, int]]]: adjusted = set(map(lambda t: (t[0] + xx, t[1] + yy), SolverDay20._monster_shape())) try: for x, y in adjusted: if not image[y][x] == "#": return None return adjusted except IndexError: return None if __name__ == '__main__': SolverDay20(PuzzleDownloader(day=20, parser=SolverDay20.parser).get_puzzle()).run()
@staticmethod @groupwise_parser def parser(group: Iterable[str]) -> List[str]: answers = [] for answer_per_person in group: no_blanks = answer_per_person.replace(" ", "") answers.append(no_blanks) return answers def part1(self) -> int: count = 0 for answers_per_group in self.puzzle.data: answers_in_group = set() for answers_per_person in answers_per_group: answers_in_group.update(list(answers_per_person)) count += len(answers_in_group) return count def part2(self) -> int: count = 0 for answers_per_group in self.puzzle.data: as_sets = map(set, answers_per_group) # type: ignore common_answers = reduce(set.intersection, as_sets) count += len(common_answers) return count if __name__ == '__main__': SolverDay6(PuzzleDownloader(day=6, parser=SolverDay6.parser).get_puzzle()).run()