def part2(lines: list[str]): rotations = { "L": { 90: counterclockwise_90, 180: rotate, 270: clockwise_90 }, "R": { 90: clockwise_90, 180: rotate, 270: counterclockwise_90 }, } pos = (0, 0) waypoint = (10, 1) for line in lines: cmd = line[0] number = utils.ints(line)[0] if cmd == "F": pos = utils.tuple_add(pos, tuple(number * i for i in waypoint)) elif cmd in "LR": waypoint = rotations[cmd][number](waypoint) elif cmd in DIRECTIONS.keys(): waypoint = utils.tuple_add( waypoint, tuple(number * i for i in DIRECTIONS[cmd])) return abs(pos[0]) + abs(pos[1])
def simulate_step(moons: List[Moon]) -> None: all_pairs = list(combinations(moons, 2)) for a, b in all_pairs: a.change_velocity(b) for moon in moons: moon.position = tuple_add(moon.position, moon.velocity)
def part1(lines: list[str]): rotations = "ESWN" dir_ = "E" pos = (0, 0) for line in lines: cmd = line[0] number = utils.ints(line)[0] if cmd == "F": pos = utils.tuple_add(pos, tuple(number * i for i in DIRECTIONS[dir_])) elif cmd in "LR": number = number // 90 idx = rotations.index(dir_) m = 1 if cmd == "R" else -1 idx += m * number dir_ = rotations[idx % 4] elif cmd in DIRECTIONS.keys(): pos = utils.tuple_add(pos, tuple(number * i for i in DIRECTIONS[cmd])) return abs(pos[0]) + abs(pos[1])
def main(): input_txt = utils.get_input(24).rstrip() lines = input_txt.split("\n") map_ = defaultdict(bool) for line in lines: start = (0, 0, 0) i = 0 while i < len(line): if line[i] in directions: start = utils.tuple_add(start, directions[line[i]]) i += 1 elif line[i:i + 2] in directions: start = utils.tuple_add(start, directions[line[i:i + 2]]) i += 2 else: raise ValueError map_[start] = not map_[start] print(sum(1 for k, v in map_.items() if v)) part2(map_)
def has_occupied_seat_in_direction( pos: tuple[int, int], direction: tuple[int, int], occupied: set[tuple[int, int]], empty: set[tuple[int, int]], ): new_x, new_y = utils.tuple_add(pos, direction) if new_x < 0 or new_x > MAX_X or new_y < 0 or new_y > MAX_Y: return None elif (new_x, new_y) in empty: return False elif (new_x, new_y) in occupied: return True else: return has_occupied_seat_in_direction((new_x, new_y), direction, occupied, empty)
def part2(map_): for _ in range(100): to_be_checked = {t for t, v in map_.items() if v} for t in list(to_be_checked): to_be_checked.update( utils.tuple_add(t, d) for d in directions.values()) new_map = defaultdict(bool) for t in to_be_checked: number_of_black_neighbors = calc_black_neighbors(map_, t) is_black = map_[t] if is_black and number_of_black_neighbors in (1, 2): new_map[t] = True elif not is_black and number_of_black_neighbors == 2: new_map[t] = True map_ = new_map print(sum(1 for t, v in map_.items() if v))
def run_robot(intcode, starting_tile): board = defaultdict(int) machine = Machine(0, copy.copy(intcode), deque(), 0) machine.inputs.append(starting_tile) state = machine.state position = (0, 0) facing = Direction.UP while state != State.HALT: state, out = machine.run() if len(out) != 2: raise Exception(f"Output from intcode machine != 2: {len(out)}") if out[0] == 0: board[position] = 0 elif out[0] == 1: board[position] = 1 else: raise Exception( f"First output value does not indicate black or white: {out[0]}" ) if out[1] != 0 and out[1] != 1: raise Exception( f"Second output value does not indicate left or right: {out[1]}" ) facing = turn[(out[1], facing)] position = tuple_add(position, facing.value) if state == State.WAIT_FOR_INPUT: machine.out.clear() machine.inputs.append(board[position]) continue return board
def calculate_adjacent(pos: tuple[int, int]) -> set[tuple[int, int]]: return {utils.tuple_add(pos, dir_) for dir_ in DIRS}
def calc_black_neighbors(map_, t): return sum([map_[utils.tuple_add(t, d)] for d in directions.values()])