123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- #!/usr/bin/python3
- import sys
- right, down, left, up = (1, 0), (0, 1), (-1, 0), (0, -1)
- cube_regions = {
- 1: [(50, 0), (99, 49)],
- 2: [(100, 0), (149, 49)],
- 3: [(50, 50), (99, 99)],
- 4: [(0, 100), (49, 149)],
- 5: [(50, 100), (99, 149)],
- 6: [(0, 150), (49, 199)],
- }
- cube_transitions = {
- 1: {
- right: (2, right, lambda x, y: (100, y)),
- down: (3, down, lambda x, y: (x, 50)),
- left: (4, right, lambda x, y: (0, 149 - y)),
- up: (6, right, lambda x, y: (0, 100 + x))
- },
- 2: {
- right: (5, left, lambda x, y: (99, 149 - y)),
- down: (3, left, lambda x, y: (99, x - 50)),
- left: (1, left, lambda x, y: (99, y)),
- up: (6, up, lambda x, y: (x - 100, 199))
- },
- 3: {
- right: (2, up, lambda x, y: (50 + y, 49)),
- down: (5, down, lambda x, y: (x, 100)),
- left: (4, down, lambda x, y: (y - 50, 100)),
- up: (1, up, lambda x, y: (x, 49))
- },
- 4: {
- right: (5, right, lambda x, y: (50, y)),
- down: (6, down, lambda x, y: (x, 150)),
- left: (1, right, lambda x, y: (50, 149 - y)),
- up: (3, right, lambda x, y: (50, 50 + x))
- },
- 5: {
- right: (2, left, lambda x, y: (149, 149 - y)),
- down: (6, left, lambda x, y: (49, 100 + x)),
- left: (4, left, lambda x, y: (49, y)),
- up: (3, up, lambda x, y: (x, 99))
- },
- 6: {
- right: (5, up, lambda x, y: (y - 100, 149)),
- down: (2, down, lambda x, y: (100 + x, 0)),
- left: (1, down, lambda x, y: (y - 100, 0)),
- up: (4, up, lambda x, y: (x, 149))
- },
- }
- def wrap_around_position(grid, xlimits, ylimits, position, move):
- x, y = position
- mx, my = move
- #print(x, y, mx, my, '-> ', end='')
- # horizontal movement
- if mx > 0 and x + mx > xlimits[y][1]:
- x = xlimits[y][0]
- mx = 0
- elif mx < 0 and x + mx < xlimits[y][0]:
- x = xlimits[y][1]
- mx = 0
- # vertical movement
- if my > 0 and y + my > ylimits[x][1]:
- y = ylimits[x][0]
- my = 0
- elif my < 0 and y + my < ylimits[x][0]:
- y = ylimits[x][1]
- my = 0
- #print(x, y, mx, my)
- return (x + mx, y + my)
- def wrap_around_position_cubic(grid, position, xlimits, move, side):
- x, y = position
- mx, my = move
- nx, ny = x + mx, y + my
- ul, lr = cube_regions[side]
- sx1, sy1 = ul
- sx2, sy2 = lr
- #print(x, y, mx, my, sx1, sy1, sx2, sy2)
- # horizontal cubic wrap around
- if abs(mx) > 0 and (nx < sx1 or nx > sx2):
- print('case 1 true')
- side, new_move, new_xy = cube_transitions[side][move]
- print(x, y, new_xy(nx, ny))
- x, y = new_xy(nx, ny)
- mx, my = new_move
- elif abs(my) > 0 and (ny < sy1 or ny > sy2):
- print('case 2 true')
- side, new_move, new_xy = cube_transitions[side][move]
- print(x, y, new_xy(nx, ny))
- x, y = new_xy(nx, ny)
- mx, my = new_move
- else:
- x = nx
- y = ny
- return (x, y), (mx, my), side
- def collision(grid, xlimits, ylimits, position, cubic=False):
- x, y = position
- #print(x, y, xlimits[y][0], x - xlimits[y][0], len(grid), len(grid[y]))
- return grid[y][x - xlimits[y][0]] == '#'
- def solution(cubic=False):
- path = None
- grid = []
- xlimits = []
- ylimits = []
- print(cube_regions)
- print(cube_transitions)
- side = 1
- for line in sys.stdin:
- stripped = line.strip()
- if stripped == '':
- path = next(sys.stdin).strip()
- else:
- offset = line.rstrip().count(' ')
- grid.append(stripped)
- xlimits.append((offset, offset + len(stripped) - 1))
-
- maxxl = 0
- for xl in xlimits:
- maxxl = max(maxxl, xl[1])
- for x in range(maxxl + 1):
- offset = 0
- count = 0
- count_offset = True
- for xl in xlimits:
- if count_offset:
- if x >= xl[0] and x <= xl[1]:
- count_offset = False
- else:
- offset += 1
- else:
- if x >= xl[0] and x <= xl[1]:
- count += 1
- ylimits.append((offset, offset + count))
- print(grid)
- print(xlimits)
- print(ylimits)
- print(path)
- position = (xlimits[0][0], 0)
- facing = (1, 0)
- path = [[int(num) for num in p.split('L')] for p in path.split('R')]
- for i, rmove in enumerate(path):
- for j, lmove in enumerate(rmove):
- print(f'moving {lmove} (now at position {position} facing {facing} on side {side})')
- for k in range(int(lmove)):
- if not cubic:
- next_position = wrap_around_position(grid, xlimits, ylimits, position, facing)
- if not collision(grid, xlimits, ylimits, next_position):
- position = next_position
- else:
- break
- else:
- next_position, next_face, next_side = wrap_around_position_cubic(grid, position, xlimits, facing, side)
- if not collision(grid, xlimits, ylimits, next_position):
- position = next_position
- facing = next_face
- side = next_side
- else:
- break
- print(position)
- if j != len(rmove) - 1:
- facing = (facing[1], -facing[0])
- print(f'turning left (now facing {facing})')
- if i != len(path) - 1:
- facing = (-facing[1], facing[0])
- print(f'turning right (now facing {facing})')
-
- facing_number = {(1, 0): 0, (0, 1): 1, (-1, 0): 2, (0, -1): 3}
- password = 1000 * (position[1] + 1) + 4 * (position[0] + 1) + facing_number[facing]
- print(f'the password is {password}')
- if sys.argv[1] in '1':
- solution()
- else:
- solution(cubic=True)
|