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]]