199 lines
5.5 KiB
Python
199 lines
5.5 KiB
Python
|
import sys
|
||
|
import math
|
||
|
from enum import Enum
|
||
|
|
||
|
|
||
|
class Coordinate:
|
||
|
def __init__(self, r, c):
|
||
|
self.r = r
|
||
|
self.c = c
|
||
|
|
||
|
def __str__(self):
|
||
|
return str((self.r, self.c))
|
||
|
|
||
|
|
||
|
class Direction(Enum):
|
||
|
SOUTH = 1
|
||
|
EAST = 2
|
||
|
NORTH = 3
|
||
|
WEST = 4
|
||
|
|
||
|
|
||
|
class Game:
|
||
|
def __init__(self, city_map):
|
||
|
self.city_map = city_map
|
||
|
self.bender = Bender(self.city_map)
|
||
|
|
||
|
def run(self):
|
||
|
while self.bender.alive:
|
||
|
self.bender.step()
|
||
|
|
||
|
|
||
|
class Bender:
|
||
|
def __init__(self, city_map, position=None):
|
||
|
self.direction = Direction.SOUTH
|
||
|
self._position = position
|
||
|
self.fury = False
|
||
|
self.alive = True
|
||
|
self.city_map = city_map
|
||
|
self.invert = False
|
||
|
self.instructions = []
|
||
|
|
||
|
if not self.position:
|
||
|
for i, r in enumerate(self.city_map):
|
||
|
if '@' in r:
|
||
|
r, c = i, ''.join(r).find('@')
|
||
|
self.position = Coordinate(r, c)
|
||
|
@property
|
||
|
def position(self):
|
||
|
return self._position
|
||
|
|
||
|
@position.setter
|
||
|
def position(self, value):
|
||
|
self._position = value
|
||
|
# self.print_map()
|
||
|
|
||
|
def print_map(self, file=sys.stderr):
|
||
|
for r, row in enumerate(self.city_map):
|
||
|
if r != self.position.r:
|
||
|
line = ''.join(row)
|
||
|
else:
|
||
|
line = ''.join(row[:self.position.c]) + '*' + ''.join(row[self.position.c+1:])
|
||
|
print(line, file=file)
|
||
|
|
||
|
def step(self):
|
||
|
next_item = self.get_next_item()
|
||
|
|
||
|
if next_item == '#' or (next_item == 'X' and not self.fury):
|
||
|
self.bypass_obstacle()
|
||
|
self.step()
|
||
|
else:
|
||
|
self.step_forward()
|
||
|
|
||
|
if next_item == 'X' and self.fury:
|
||
|
self.city_map[self.position.r][self.position.c] = ' '
|
||
|
|
||
|
elif next_item == 'B':
|
||
|
self.fury = not self.fury
|
||
|
|
||
|
elif next_item == 'T':
|
||
|
self.beam_me_up()
|
||
|
|
||
|
elif next_item == 'I':
|
||
|
self.invert = not self.invert
|
||
|
|
||
|
elif next_item == 'S':
|
||
|
self.direction = Direction.SOUTH
|
||
|
|
||
|
elif next_item == 'E':
|
||
|
self.direction = Direction.EAST
|
||
|
|
||
|
elif next_item == 'N':
|
||
|
self.direction = Direction.NORTH
|
||
|
|
||
|
elif next_item == 'W':
|
||
|
self.direction = Direction.WEST
|
||
|
|
||
|
elif next_item == '$':
|
||
|
self.alive = False
|
||
|
for instruction in self.instructions:
|
||
|
print(instruction)
|
||
|
|
||
|
self.check_loop()
|
||
|
|
||
|
def check_loop(self):
|
||
|
if len(self.instructions) > 1000:
|
||
|
print('LOOP')
|
||
|
self.alive = False
|
||
|
|
||
|
def beam_me_up(self):
|
||
|
b_r, b_c = self.position.r, self.position.c
|
||
|
|
||
|
for i, row in enumerate(self.city_map):
|
||
|
if 'T' in row:
|
||
|
t_r, t_c = i, ''.join(row).find('T')
|
||
|
if t_r != b_r or t_c != b_c:
|
||
|
self.position = Coordinate(t_r, t_c)
|
||
|
return
|
||
|
|
||
|
def bypass_obstacle(self):
|
||
|
if not self.invert:
|
||
|
self.direction = Direction.SOUTH
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
self.direction = Direction.EAST
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
self.direction = Direction.NORTH
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
self.direction = Direction.WEST
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
else:
|
||
|
self.direction = Direction.WEST
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
self.direction = Direction.NORTH
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
self.direction = Direction.EAST
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
self.direction = Direction.SOUTH
|
||
|
if not self.is_obstacle(self.get_next_item()):
|
||
|
return
|
||
|
|
||
|
def step_forward(self):
|
||
|
if self.direction == Direction.SOUTH:
|
||
|
self.position.r += 1
|
||
|
self.instructions.append('SOUTH')
|
||
|
elif self.direction == Direction.NORTH:
|
||
|
self.position.r -= 1
|
||
|
self.instructions.append('NORTH')
|
||
|
elif self.direction == Direction.EAST:
|
||
|
self.position.c += 1
|
||
|
self.instructions.append('EAST')
|
||
|
elif self.direction == Direction.WEST:
|
||
|
self.position.c -= 1
|
||
|
self.instructions.append('WEST')
|
||
|
|
||
|
# self.print_map()
|
||
|
|
||
|
def get_next_item(self):
|
||
|
if self.direction == Direction.SOUTH:
|
||
|
return self.city_map[self.position.r + 1][self.position.c]
|
||
|
elif self.direction == Direction.NORTH:
|
||
|
return self.city_map[self.position.r - 1][self.position.c]
|
||
|
elif self.direction == Direction.EAST:
|
||
|
return self.city_map[self.position.r][self.position.c + 1]
|
||
|
elif self.direction == Direction.WEST:
|
||
|
return self.city_map[self.position.r][self.position.c - 1]
|
||
|
|
||
|
def is_obstacle(self, next_item):
|
||
|
if self.fury:
|
||
|
return next_item == '#'
|
||
|
else:
|
||
|
return next_item == '#' or next_item == 'X'
|
||
|
|
||
|
|
||
|
def main():
|
||
|
l, c = [int(i) for i in input().split()]
|
||
|
city_map = []
|
||
|
for i in range(l):
|
||
|
city_map.append(list(input()))
|
||
|
|
||
|
game = Game(city_map)
|
||
|
game.run()
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|