Advent of Code 2022 day 22
Part 2 was incredibly painful. Maybe hand-coding if statements isn’t the most
sensible idea.
It appears it wasn’t just me who found it painful:
Part 1
def get_card(data):
return data.splitlines()[:-2]
def clean_card(card):
max_col = max(len(row) for row in card)
return [
extend_line(row, max_col) for row in card
]
def extend_line(line, col):
return line + (" "*(col-len(line)))
with open("22.txt") as f:
data = f.read()
card = clean_card(get_card(data))
instructions = data.splitlines()[-1]
def get_instructions(instructions):
instruction = ""
for x in instructions:
if x == "R" or x == "L":
yield instruction
instruction = ""
instruction += x
yield instruction
def change_direction(instruction, direction):
rotate = instruction[0]
if rotate == "R":
return (int(instruction[1:]), (direction+1)%4)
elif rotate == "L":
return (int(instruction[1:]), (direction-1)%4)
else:
return (int(instruction), direction)
def get_answer(card, instructions):
def valid(to, direction):
row, col = to
if row < 0:
return valid((len(card)-1, col), direction)
elif row == len(card):
return valid((0, col), direction)
elif col < 0:
return valid((row, len(card[row])-1), direction)
elif col >= len(card[row]):
return valid((row, 0), direction)
elif card[row][col] == "#":
return False
elif card[row][col] == ".":
return to
elif card[row][col] == " ":
return next_move(to, direction)
def next_move(start, direction):
row, col = start
if direction == 0:
to = (row, col+1)
elif direction == 1:
to = (row+1, col)
elif direction == 2:
to = (row, col-1)
elif direction == 3:
to = (row-1, col)
return valid(to, direction)
def go(start, distance, direction):
if distance == 0:
return start
if to := next_move(start, direction):
return go(to, distance-1, direction)
elif to is False:
return start
position = next_move((0, 0), 0)
direction = 0
for instruction in get_instructions(instructions):
distance, direction = change_direction(instruction, direction)
position = go(position, distance, direction)
row, col = position
return (row+1)*1000 + (col+1)*4 + direction
print(get_answer(card, instructions))
Part 2
# Not going to bother generalising
def get_face(row, col):
if row < 50:
if col < 100:
return 0
elif col < 150:
return 1
elif row < 100:
return 2
elif row < 150:
# yes, I know, this is the wrong way round
# I messed up.
if col < 50:
return 4
return 3
return 5
def get_cube(data):
lines = data.splitlines()[:-2]
cube = dict()
for row, line in enumerate(lines):
for col, char in enumerate(line):
if char != " ":
cube[(get_face(row, col), row%50, col%50)] = char
return cube
def face_to_value(position, direction):
face, row, col = position
if face == 0:
col += 50
elif face == 1:
col += 100
elif face == 2:
row += 50
col += 50
elif face == 3:
row += 100
col += 50
elif face == 4:
row += 100
elif face == 5:
row += 150
return (row+1)*1000 + (col+1)*4 + direction % 4
with open("22.txt") as f:
data = f.read()
cube = get_cube(data)
instructions = data.splitlines()[-1]
def get_instructions(instructions):
instruction = ""
for x in instructions:
if x == "R" or x == "L":
yield instruction
instruction = ""
instruction += x
yield instruction
def change_direction(instruction, direction):
rotate = instruction[0]
if rotate == "R":
return (int(instruction[1:]), (direction+1)%4)
elif rotate == "L":
return (int(instruction[1:]), (direction-1)%4)
else:
return (int(instruction), direction)
def get_answer(card, instructions):
def next_move(start, direction):
face, row, col = start
if direction % 4 == 0:
to = (face, row, col+1)
elif direction % 4 == 1:
to = (face, row+1, col)
elif direction % 4 == 2:
to = (face, row, col-1)
elif direction % 4 == 3:
to = (face, row-1, col)
face, row, col = to
new_direction = direction
if row < 0:
if face == 0:
to = (5, col, 0)
new_direction = direction+1
elif face == 1:
to = (5, 49, col)
elif face == 2:
to = (0, 49, col)
elif face == 3:
to = (2, 49, col)
elif face == 4:
to = (2, col, 0)
new_direction = direction+1
elif face == 5:
to = (4, 49, col)
elif row >= 50:
if face == 0:
to = (2, 0, col)
elif face == 1:
to = (2, col, 49)
new_direction = direction+1
elif face == 2:
to = (3, 0, col)
elif face == 3:
to = (5, col, 49)
new_direction = direction+1
elif face == 4:
to = (5, 0, col)
elif face == 5:
to = (1, 0, col)
elif col < 0:
if face == 0:
to = (4, 49-row, 0)
new_direction = direction+2
elif face == 1:
to = (0, row, 49)
elif face == 2:
to = (4, 0, row)
new_direction = direction-1
elif face == 3:
to = (4, row, 49)
elif face == 4:
to = (0, 49-row, 0)
new_direction = direction+2
elif face == 5:
to = (0, 0, row)
new_direction = direction-1
elif col >= 50:
if face == 0:
to = (1, row, 0)
elif face == 1:
to = (3, 49-row, 49)
new_direction = direction+2
elif face == 2:
to = (1, 49, row)
new_direction = direction-1
elif face == 3:
to = (1, 49-row, 49)
new_direction = direction+2
elif face == 4:
to = (3, row, 0)
elif face == 5:
to = (3, 49, row)
new_direction = direction-1
if card[to] == "#":
return direction % 4, False
elif card[to] == ".":
return new_direction % 4, to
def go(start, distance, direction):
if distance == 0:
return direction, start
new_direction, to = next_move(start, direction)
if to:
return go(to, distance-1, new_direction)
elif to is False:
return new_direction, start
position = (0, 0, 0)
direction = 0
for instruction in get_instructions(instructions):
distance, direction = change_direction(instruction, direction)
direction, position = go(position, distance, direction)
return face_to_value(position, direction)
print(get_answer(cube, instructions))