Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from collections import defaultdict
- import itertools as it
- def _rebuild_path(path_map, end):
- path = [end]
- current_source = path_map[end]
- while current_source is not None:
- path.insert(0, current_source)
- current_source = path_map[current_source]
- return path
- def dijkstra(source, is_end):
- to_visit = set([source])
- came_from = defaultdict(lambda: None)
- dist_to = defaultdict(lambda: float('inf'))
- dist_to[source] = 0
- while to_visit:
- vertex = min(to_visit, key=lambda v: dist_to[v])
- to_visit.remove(vertex)
- local_print(vertex)
- if is_end(vertex):
- return _rebuild_path(came_from, end)
- for n_vertex in neighbors(vertex):
- alt = dist_to[vertex] + 1
- if dist_to[n_vertex] is None or alt < dist_to[n_vertex]:
- dist_to[n_vertex] = alt
- came_from[n_vertex] = vertex
- N = int(input())
- M = []
- for _ in range(N):
- M.append(list(input()))
- local_print("N = %s" % N)
- DIRECTIONS = {
- 'North': (0, -1), 'South': (0, 1),
- 'East': (1, 0), 'West': (-1, 0),
- }
- start = None
- ghosts = []
- for x, y in it.product(range(N), range(N)):
- v = M[x][y]
- if v == 'C':
- start = (x, y)
- M[x][y] = '.'
- elif v == 'M':
- ghosts.append((x, y))
- M[x][y] = '.'
- elif v == 'O':
- past = (x, y)
- start = start, tuple(ghosts)
- del ghosts
- def in_bounds(x, y):
- r = 0 <= x < N and 0 <= y < N
- #local_print("in_bounds(%s, %s) = %s" % (x, y, r))
- return r
- def is_wall(x, y):
- r = M[x][y] == '#'
- #local_print("is_wall(%s, %s) = %s" % (x, y, r))
- return r
- def can_move_to(x, y):
- r = in_bounds(x, y) and not is_wall(x, y)
- #local_print("can_move_to(%s, %s) = %s" % (x, y, r))
- return r
- def move_pos(pos, diff):
- x, y = pos
- dx, dy = diff
- nx, ny = (x + dx, y + dy)
- if nx < 0:
- nx = N - 1
- elif nx == N:
- nx = 0
- return nx, ny
- def all_ghost_moves(ghosts):
- all_moves = map(lambda x: (x[0][0], move_pos(x[0][1], x[1])), it.product(enumerate(ghosts), DIRECTIONS.values()))
- valid_moves = list(filter(lambda p: can_move_to(p[1][0], p[1][1]), all_moves))
- #local_print("valid_moves: %s" % (valid_moves,))
- groups = map(lambda x: x[1], it.groupby(valid_moves, key=lambda x: x[0]))
- return map(lambda x: map(tuple, x[1]), it.product(*groups))
- def neighbors(node):
- pos, ghosts = node
- x, y = pos
- for direction in DIRECTIONS.values():
- nx, ny = move_pos(pos, direction)
- if not can_move_to(nx, ny):
- continue
- local_print("can_move_to: %s" % ((nx, ny),))
- for new_ghosts in all_ghost_moves(ghosts):
- local_print("new_ghosts: %s" % (new_ghosts,))
- if pos in new_ghosts:
- continue
- yield pos, new_ghosts
- local_print("start: %s" % (start,))
- search = dijkstra(start, lambda pg: pg[0] == past)
- print(len(search))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement