elif (turn := self._turn.get(action)) is not None: radians = math.radians(value * turn) self.direction *= complex(math.cos(radians), math.sin(radians)) elif action == self._forward: self.forward(value) else: raise ValueError(f"unknown action '{action}'") def parse_puzzle_input( puzzle_input: Sequence[str]) -> Sequence[Tuple[str, int]]: return tuple((s[0], int(s[1:])) for s in puzzle_input) def solve_first_part(puzzle_input: Sequence[str]) -> int: intructions = parse_puzzle_input(puzzle_input) ship = Ship() for action, value in intructions: ship.execute(action, value) di, dj = math.fabs(ship.coordinates.real), math.fabs(ship.coordinates.imag) return round(di) + round(dj) def solve_second_part(puzzle_input: Sequence[str]) -> int: return -1 if __name__ == "__main__": puzzle_input = get_puzzle_input("day12") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
def iter_triples_that_sum_to_target( integer_set: Set[int], target: int ) -> Iterable[Tuple[int, int]]: for i in integer_set: diff = target - i for pair in iter_pairs_that_sum_to_target(integer_set, diff): yield i, *pair def solve_first_part(puzzle_input: Sequence[str]) -> int: integer_set = set(parse_puzzle_input(puzzle_input)) try: a, b = next(iter_pairs_that_sum_to_target(integer_set, PUZZLE_TARGET)) except StopIteration as e: raise ValueError(f"found no pair that sum to {PUZZLE_TARGET}") from e return a * b def solve_second_part(puzzle_input: Sequence[str]) -> int: integer_set = set(parse_puzzle_input(puzzle_input)) try: a, b, c = next(iter_triples_that_sum_to_target(integer_set, PUZZLE_TARGET)) except StopIteration as e: raise ValueError(f"found no triple that sum to {PUZZLE_TARGET}") from e return a * b * c if __name__ == "__main__": puzzle_input = get_puzzle_input("day01") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
return False return outer_contains_inner def make_count_func(rules: Dict[str, Rule]) -> Callable[[str], int]: @cache def count_contained_bags(outer: str) -> int: return sum(bag.quantity + count_contained_bags(bag.color) * bag.quantity for bag in rules[outer].content) return count_contained_bags def solve_first_part(puzzle_input: Sequence[str]) -> int: rules = parse_puzzle_input(puzzle_input) outer_contains_inner = make_search_func(rules) return sum(outer_contains_inner(color, "shiny gold") for color in rules) def solve_second_part(puzzle_input: Sequence[str]) -> int: rules = parse_puzzle_input(puzzle_input) count_contained_bags = make_count_func(rules) return count_contained_bags("shiny gold") if __name__ == "__main__": puzzle_input = get_puzzle_input("day07") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
def count_occupied_seats(self) -> int: return sum(s.occupied for s in self._sparse_grid.values()) def stabilize(self) -> int: while True: if self.update_seats() == 0: return self.count_occupied_seats() def to_grid(self): range_i, range_j = self._dim grid = [["." for _ in range_i] for _ in range_j] for k, v in self._sparse_grid.items(): grid[int(k.real)][int(k.imag)] = v return grid def __str__(self) -> str: return "\n".join("".join(r) for r in self.to_grid()) def solve_first_part(puzzle_input: Sequence[str]) -> int: return SeatGrid(puzzle_input, 4, False).stabilize() def solve_second_part(puzzle_input: Sequence[str]) -> int: return SeatGrid(puzzle_input, 5, True).stabilize() if __name__ == "__main__": puzzle_input = get_puzzle_input("day11") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
counter = {1: 0, 2: 0, 3: 0} rating = 0 for a in adapters: counter[a - rating] += 1 rating = a return counter def count_arrangements(adapters: Sequence[int]) -> int: diffs = [1, 2, 3] counter = {0: 1} for a in adapters: counter[a] = sum(map(lambda i: counter.get(a - i, 0), diffs)) return counter[adapters[-1]] def solve_first_part(puzzle_input: Sequence[str]) -> int: adapters = parse_puzzle_input(puzzle_input) counter = count_differences(adapters) return counter[1] * counter[3] def solve_second_part(puzzle_input: Sequence[str]) -> int: adapters = parse_puzzle_input(puzzle_input) return count_arrangements(adapters) if __name__ == "__main__": puzzle_input = get_puzzle_input("day10") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
def validate_first_policy(item: PuzzleItem) -> bool: letter_count = sum(char is item.letter for char in item.password) return item.x1 <= letter_count <= item.x2 def get_char(x: str, one_based_index: int) -> Optional[str]: zero_based_index = one_based_index - 1 try: return x[zero_based_index] except IndexError: return def validate_second_policy(item: PuzzleItem) -> bool: a, b = get_char(item.password, item.x1), get_char(item.password, item.x2) return (a == item.letter or b == item.letter) and a != b def solve_first_part(puzzle_input: Sequence[str]) -> int: return count_valid_items(puzzle_input, validate_first_policy) def solve_second_part(puzzle_input: Sequence[str]) -> int: return count_valid_items(puzzle_input, validate_second_policy) if __name__ == "__main__": puzzle_input = get_puzzle_input("day02") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
(7, 1), (1, 2), ) def count_trees_in_path(puzzle_input: Sequence[str], right: int, down: int) -> int: count = 0 i, j = 0, 0 while i < len(puzzle_input) - down: i += down row = puzzle_input[i] j = (j + right) % len(row) count += row[j] == "#" return count def solve_first_part(puzzle_input: Sequence[str]) -> int: return count_trees_in_path(puzzle_input, *PUZZLE_SLOPES[0]) def solve_second_part(puzzle_input: Sequence[str]) -> int: return math.prod( count_trees_in_path(puzzle_input, right, down) for right, down in PUZZLE_SLOPES[1:] ) if __name__ == "__main__": puzzle_input = get_puzzle_input("day03") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
from aoc2020.puzzle import print_puzzle def parse_puzzle_input(puzzle_input: Sequence[str]) -> Sequence[Sequence[str]]: return tuple(tuple(v) for k, v in groupby(puzzle_input, lambda x: len(x) > 0) if k) def count_any(answers: Sequence[str]) -> int: return len(set(chain.from_iterable(answers))) def count_all(answers: Sequence[str]) -> int: group_size = len(answers) counter = Counter(chain.from_iterable(answers)) return sum(c == group_size for c in counter.values()) def solve_first_part(puzzle_input: Sequence[str]) -> int: answers_list = parse_puzzle_input(puzzle_input) return sum(count_any(a) for a in answers_list) def solve_second_part(puzzle_input: Sequence[str]) -> int: answers_list = parse_puzzle_input(puzzle_input) return sum(count_all(a) for a in answers_list) if __name__ == "__main__": puzzle_input = get_puzzle_input("day06") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
total = integers[lower] + integers[upper - 1] while upper <= len(integers): if total < target: total += integers[upper] upper += 1 elif total > target: total -= integers[lower] lower += 1 else: return tuple(integers[lower:upper]) raise ValueError("did not find any continuous tuple") def solve_first_part(puzzle_input: Sequence[str], preamble: int = PUZZLE_PREAMBLE) -> int: integers = parse_puzzle_input(puzzle_input) return find_weakness(integers, preamble) def solve_second_part(puzzle_input: Sequence[str], preamble: int = PUZZLE_PREAMBLE) -> int: integers = parse_puzzle_input(puzzle_input) weakness = find_weakness(integers, preamble) contiguous_tuple = find_contiguous_tuple(integers, weakness) return min(contiguous_tuple) + max(contiguous_tuple) if __name__ == "__main__": puzzle_input = get_puzzle_input("day09") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
operation, argument = instructions[i] if operation is Operation.ACC: accumulator += argument i += argument if operation is Operation.JMP else 1 return accumulator def solve_first_part(puzzle_input: Sequence[str]) -> int: instructions = parse_puzzle_input(puzzle_input) return run_boot_code(instructions, True) def solve_second_part(puzzle_input: Sequence[str]) -> int: instructions = parse_puzzle_input(puzzle_input) for i in range(len(instructions)): operation, argument = instructions[i] if operation is Operation.ACC: continue new_operation = Operation.JMP if operation is Operation.NOP else Operation.NOP instructions[i] = new_operation, argument try: return run_boot_code(instructions) except RuntimeError: instructions[i] = operation, argument raise ValueError("no permutation fixed the instructions") if __name__ == "__main__": puzzle_input = get_puzzle_input("day08") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
puzzle_input: Sequence[str]) -> Sequence[Dict[str, str]]: return tuple( dict( field.split(":") for field in chain.from_iterable(line.split() for line in v)) for k, v in groupby(puzzle_input, lambda x: len(x) > 0) if k) def solve_first_part(puzzle_input: Sequence[str]) -> int: passeports = parse_puzzle_input(puzzle_input) expected_fields = set(f.name for f in fields(Passeport)) - {"cid"} return sum(expected_fields <= p.keys() for p in passeports) def solve_second_part(puzzle_input: Sequence[str]) -> int: passeports = parse_puzzle_input(puzzle_input) valid_count = 0 for kwargs in passeports: try: Passeport(**kwargs) except (TypeError, AssertionError): pass else: valid_count += 1 return valid_count if __name__ == "__main__": puzzle_input = get_puzzle_input("day04") print_puzzle(puzzle_input, solve_first_part, solve_second_part)
from aoc2020.input import get_puzzle_input from aoc2020.puzzle import print_puzzle PUZZLE_MAPPING = {"F": "0", "B": "1", "L": "0", "R": "1"} def parse_puzzle_input(puzzle_input: Sequence[str]) -> Sequence[int]: return tuple(int("".join(PUZZLE_MAPPING[c] for c in p), 2) for p in puzzle_input) def solve_first_part(puzzle_input: Sequence[str]) -> int: return max(parse_puzzle_input(puzzle_input)) def solve_second_part(puzzle_input: Sequence[str]) -> int: seat_id_set = set(parse_puzzle_input(puzzle_input)) for seat_id in range(min(seat_id_set) + 1, max(seat_id_set)): if ( seat_id not in seat_id_set and seat_id + 1 in seat_id_set and seat_id - 1 in seat_id_set ): return seat_id raise ValueError("could not find the seat id") if __name__ == "__main__": puzzle_input = get_puzzle_input("day05") print_puzzle(puzzle_input, solve_first_part, solve_second_part)