Advent of Code 2022 day 23
Relatively straightforward, to the extent that I was able to program everything within one file, without having to split off for part 2. Used currying to rotate through the conditionals.
with open("23.txt") as f: # with open("23_test.txt") as f: # with open("23_test_test.txt") as f: lines = f.read().splitlines() def clean_card(card): min_col = min([ col for col in range(len(card[0])) for row in range(len(card)) if card[row][col] == "#" ]) max_col = max([ col for col in range(len(card[0])) for row in range(len(card)) if card[row][col] == "#" ]) min_row = min([ row for col in range(len(card[0])) for row in range(len(card)) if card[row][col] == "#" ]) max_row = max([ row for col in range(len(card[0])) for row in range(len(card)) if card[row][col] == "#" ]) return [ [ card[row][col] for col in range(min_col, max_col+1) ] for row in range(min_row, max_row+1) ] def print_card(card): card = clean_card(card) print( "\n".join([ "".join([ card[row][col] for col in range(len(card[0])) ]) for row in range(len(card)) ]) ) def get_number_of_elves(lines): return sum([line.count("#") for line in lines]) def create_initial_card(lines): adj = 200 col = max(len(line) for line in lines) row = len(lines) return ( [ list("."*(adj + col + adj)) for _ in range(adj) ] + [ list("."*adj) + list(line) + list("."*adj) for line in lines ] + [ list("."*(adj + col + adj)) for _ in range(adj) ] ) def can_move_north(card, row, col): return all(card[row-1][col+i] == "." for i in range(-1, 2)) def can_move_south(card, row, col): return all(card[row+1][col+i] == "." for i in range(-1, 2)) def can_move_west(card, row, col): return all(card[row+i][col-1] == "." for i in range(-1, 2)) def can_move_east(card, row, col): return all(card[row+i][col+1] == "." for i in range(-1, 2)) def stay_stationary(card, row, col): return all( cond(card, row, col) for cond in ( can_move_north, can_move_south, can_move_west, can_move_east, ) ) def move_north(move_to, card, row, col): if (row-1, col) in move_to: move_to[(row-1, col)].add((row-1, col)) return move_to move_to[(row-1, col)] = {(row, col)} return move_to def move_south(move_to, card, row, col): if (row+1, col) in move_to: move_to[(row+1, col)].add((row, col)) return move_to move_to[(row+1, col)] = {(row, col)} return move_to def move_west(move_to, card, row, col): if (row, col-1) in move_to: move_to[(row, col-1)].add((row, col)) return move_to move_to[(row, col-1)] = {(row, col)} return move_to def move_east(move_to, card, row, col): if (row, col+1) in move_to: move_to[(row, col+1)].add((row, col)) return move_to move_to[(row, col+1)] = {(row, col)} return move_to conditionals = [ (can_move_north, move_north), (can_move_south, move_south), (can_move_west, move_west), (can_move_east, move_east), ] def update_move_to(move_to, card, row, col, conditionals): if stay_stationary(card, row, col): return move_to for cond in conditionals: if cond[0](card, row, col): return cond[1](move_to, card, row, col) return move_to initial_card = create_initial_card(lines) card = initial_card.copy() # print_card(card) # print(get_number_of_elves(card)) for round in range(10): move_to = dict() for row in range(len(card)): for col in range(len(card[row])): if card[row][col] == "#": move_to = update_move_to(move_to, card, row, col, conditionals) for key, values in move_to.items(): if len(values) == 1: from_row, from_col = values.pop() card[from_row][from_col] = "." to_row, to_col = key card[to_row][to_col] = "#" conditionals = conditionals[1:] + [conditionals[0]] # print(round + 1) # print_card(card) card = clean_card(card) print(len(card) * len(card[0]) - get_number_of_elves(card)) # part 2 card = create_initial_card(lines) conditionals = [ (can_move_north, move_north), (can_move_south, move_south), (can_move_west, move_west), (can_move_east, move_east), ] rounds = 0 while True: rounds += 1 move_to = dict() for row in range(len(card)): for col in range(len(card[row])): if card[row][col] == "#": move_to = update_move_to(move_to, card, row, col, conditionals) # print(move_to) # print_card(card) if len(move_to) == 0: print(rounds) exit() for key, values in move_to.items(): if len(values) == 1: from_row, from_col = values.pop() card[from_row][from_col] = "." to_row, to_col = key card[to_row][to_col] = "#" conditionals = conditionals[1:] + [conditionals[0]]