Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from time import time
- import re
- D = {0: 1, 1: 1j, 2: -1, 3: -1j}
- T = {'R': 1, 'L': -1, 'X': 0}
- def timer_func(func):
- # This function shows the execution time of
- # the function object passed
- def wrap_func(*args, **kwargs):
- t1 = time()
- result = func(*args, **kwargs)
- t2 = time()
- print(f'Function {func.__name__!r} executed in {(t2 - t1):.4f}s')
- return result
- return wrap_func
- @timer_func
- def day22(filepath, test, part2=False):
- with open(filepath) as fin:
- board_map, instructions = fin.read().split('\n\n')
- path = re.findall(r'(\d+)([LRX])', instructions)
- b_map = {}
- for y, line in enumerate(board_map.split('\n')):
- for x, c in enumerate(line):
- if c in '.#':
- b_map[complex(x, y)] = c
- cp = 0
- f = 0 # facing
- if not part2:
- if test:
- cp = 8 # current point
- for steps, turn in path:
- for _ in range(int(steps)):
- ns = cp + D[f] # next step
- if ns in b_map:
- if b_map[ns] == '.':
- cp = ns
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- if f == 0:
- if 0 <= cp.imag < 4:
- ns = complex(8, cp.imag)
- elif 4 <= cp.imag < 8:
- ns = complex(0, cp.imag)
- elif 8 <= cp.imag < 12:
- ns = complex(0, cp.imag)
- elif f == 1:
- if 0 <= cp.real < 8:
- ns = complex(cp.real, 4)
- elif 8 <= cp.real < 12:
- ns = complex(cp.real, 0)
- elif 12 <= cp.real < 16:
- ns = complex(cp.real, 8)
- elif f == 2:
- if 0 <= cp.imag < 8:
- ns = complex(11, cp.imag)
- elif 8 <= cp.imag < 12:
- ns = complex(15, cp.imag)
- elif f == 3:
- if 0 <= cp.real < 8:
- ns = complex(cp.real, 7)
- elif 8 <= cp.real < 16:
- ns = complex(cp.real, 11)
- if b_map[ns] == '.':
- cp = ns
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- f = (f + T[turn]) % 4
- else:
- cp = 50 # current point
- for steps, turn in path:
- for _ in range(int(steps)):
- ns = cp + D[f] # next step
- if ns in b_map:
- if b_map[ns] == '.':
- cp = ns
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- if f == 0:
- if 0 <= cp.imag < 100:
- ns = complex(50, cp.imag)
- elif 100 <= cp.imag < 200:
- ns = complex(0, cp.imag)
- elif f == 1:
- if 0 <= cp.real < 50:
- ns = complex(cp.real, 100)
- elif 50 <= cp.real < 150:
- ns = complex(cp.real, 0)
- elif f == 2:
- if 0 <= cp.imag < 50:
- ns = complex(149, cp.imag)
- elif 50 <= cp.imag < 150:
- ns = complex(99, cp.imag)
- elif 150 <= cp.imag < 200:
- ns = complex(49, cp.imag)
- elif f == 3:
- if 0 <= cp.real < 50:
- ns = complex(cp.real, 199)
- elif 50 <= cp.real < 100:
- ns = complex(cp.real, 149)
- elif 100 <= cp.real < 149:
- ns = complex(cp.real, 49)
- if b_map[ns] == '.':
- cp = ns
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- f = (f + T[turn]) % 4
- # part 2
- else:
- if test:
- cp = 8 # current point
- for steps, turn in path:
- for _ in range(int(steps)):
- ns = cp + D[f] # next step
- if ns in b_map:
- if b_map[ns] == '.':
- cp = ns
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- if f == 0:
- if 0 <= cp.imag < 4:
- ns = complex(15, 11 - cp.imag)
- nf = 2
- elif 4 <= cp.imag < 8:
- ns = complex(15 - (cp.imag % 4), 8)
- nf = 1
- elif 8 <= cp.imag < 12:
- ns = complex(11, 3 - (cp.imag % 8))
- nf = 2
- elif f == 1:
- if 0 <= cp.real < 4:
- ns = complex(11 - cp.real, 8)
- nf = 3
- elif 4 <= cp.real < 8:
- ns = complex(8, 11 - (cp.real % 4))
- nf = 0
- elif 8 <= cp.real < 12:
- ns = complex(3 - (cp.real % 8), 7)
- nf = 3
- elif 12 <= cp.real < 16:
- ns = complex(0, 7 - (cp.real % 12))
- nf = 0
- elif f == 2:
- if 0 <= cp.imag < 4:
- ns = complex(4 + cp.imag, 4)
- nf = 1
- elif 4 <= cp.imag < 8:
- ns = complex(12 + (cp.imag % 4), 11)
- nf = 3
- elif 8 <= cp.imag < 12:
- ns = complex(7 - (cp.imag % 8), 7)
- nf = 3
- elif f == 3:
- if 0 <= cp.real < 4:
- ns = complex(11 - cp.real, 0)
- nf = 1
- elif 4 <= cp.real < 8:
- ns = complex(8, cp.real % 4)
- nf = 0
- elif 8 <= cp.real < 12:
- ns = complex(3 - (cp.real % 8), 4)
- nf = 1
- elif 12 <= cp.real < 16:
- ns = complex(11, 7 - (cp.real % 12))
- nf = 2
- if b_map[ns] == '.':
- cp = ns
- f = nf
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- f = (f + T[turn]) % 4
- else:
- cp = 50 # current point
- for steps, turn in path:
- for _ in range(int(steps)):
- ns = cp + D[f] # next step
- if ns in b_map:
- if b_map[ns] == '.':
- cp = ns
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- # TODO fix wrapping
- if f == 0:
- if 0 <= cp.imag < 50:
- ns = complex(99, 149 - cp.imag)
- nf = 2
- elif 50 <= cp.imag < 100:
- ns = complex(100 + (cp.imag % 50), 49)
- nf = 3
- elif 100 <= cp.imag < 150:
- ns = complex(149, 49 - (cp.imag % 100))
- nf = 2
- elif 150 <= cp.imag < 200:
- ns = complex(50 + (cp.imag % 150), 149)
- nf = 3
- elif f == 1:
- if 0 <= cp.real < 50:
- ns = complex(100 + cp.real, 0)
- nf = 1
- elif 50 <= cp.real < 100:
- ns = complex(49, 150 + (cp.real % 50))
- nf = 2
- elif 100 <= cp.real < 150:
- ns = complex(99, 50 + (cp.real % 100))
- nf = 2
- elif f == 2:
- if 0 <= cp.imag < 50:
- ns = complex(0, 149 - cp.imag)
- nf = 0
- elif 50 <= cp.imag < 100:
- ns = complex(cp.imag % 50, 100)
- nf = 1
- elif 100 <= cp.imag < 150:
- ns = complex(50, 49 - (cp.imag % 100))
- nf = 0
- elif 150 <= cp.imag < 200:
- ns = complex(50 + (cp.imag % 150), 0)
- nf = 1
- elif f == 3:
- if 0 <= cp.real < 50:
- ns = complex(50, 50 + cp.real)
- nf = 0
- elif 50 <= cp.real < 100:
- ns = complex(0, 150 + (cp.real % 50))
- nf = 0
- elif 100 <= cp.real < 149:
- ns = complex(cp.real % 100, 199)
- nf = 3
- if b_map[ns] == '.':
- cp = ns
- f = nf
- elif b_map[ns] == '#':
- f = (f + T[turn]) % 4
- break
- else:
- f = (f + T[turn]) % 4
- password = int(1000 * (cp.imag + 1) + 4 * (cp.real + 1) + f)
- return password
- def main():
- assert day22('test22', test=True) == 6032
- print(f"Part 1: {day22('input22', test=False)}")
- assert day22('test22', test=True, part2=True) == 5031
- print(f"Part 2: {day22('input22', test=False, part2=True)}")
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement