Advertisement
Guest User

Untitled

a guest
Apr 21st, 2018
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.82 KB | None | 0 0
  1. # runtime
  2. # O( G(V,E) * Removable walls)
  3. # =
  4. # O(N*(|V|+|E|)) if N ~ removable walls
  5.  
  6. # function takes in a maze represented by 2D list, and returns the length of the shortest path by points traveled over
  7. # taking into account one wall can be removed but doesnt have to be
  8. def answer(maze):
  9. # all potentially removable walls
  10. walls = removableWalls(maze)
  11.  
  12. # distance with no walls removed
  13. shortestDistance = BFS(maze)
  14.  
  15. # for: remove each removable wall
  16. # update shortest distance
  17. for wall in walls:
  18. # copy maze to maze2 and remove one wall from maze2
  19. maze2 = [x[:] for x in maze]
  20. maze2[wall[0]][wall[1]] = 0
  21.  
  22. # store result to not have to run BFS again
  23. distance = BFS(maze2)
  24.  
  25. # if this distance is shorter or shortestDistance does not have a real value
  26. if (distance != -1) and (distance < shortestDistance or shortestDistance == -1):
  27. shortestDistance = distance
  28.  
  29. return shortestDistance
  30.  
  31.  
  32. # runtime
  33. # O(G(V,E))
  34. # =
  35. # O(|V|+|E|)
  36. # runtime proportional to number of edges + number of vertices, just like any BFS algorithm
  37.  
  38. # function takes in a maze represented by 2D list, and returns the length of the shortest path by points traveled over
  39. # navigates from top right to bottom left of the 2D list
  40. def BFS(maze2):
  41. # variables used to break out of several loops
  42. find1 = False
  43. find2 = False
  44.  
  45. height = len(maze2[0])
  46. width = len(maze2)
  47.  
  48. # depth layer being currently explored
  49. currentLayer = set()
  50. currentLayer.add((0, 0))
  51.  
  52. # all points we have already explored
  53. allExplored = set()
  54. allExplored.add((0, 0))
  55.  
  56. # next layer to explore
  57. nextLayer = set()
  58.  
  59. distance = 1
  60.  
  61. # while the 2D list has not been fully explored
  62. # breaks used within to break from when exit is found
  63. # avoids infinite loop condition
  64. while (currentLayer != set()):
  65.  
  66. # for each point in the current depth of the grid
  67. for point in currentLayer:
  68. # neighbors of point
  69. neighbors = navigableAdjacentPoints(maze2, point[0], point[1])
  70.  
  71. for neighbor in neighbors:
  72.  
  73. # add neighbor to nextlayer
  74. # only if neighbor was not previously explored
  75. if neighbor not in allExplored and neighbor not in currentLayer:
  76. nextLayer.add(neighbor)
  77.  
  78. # if neighbor is exit, break
  79. if neighbor == (width - 1, height - 1):
  80. find1 = True
  81. break
  82.  
  83. # if neighbor was exit, break again
  84. if find1 == True:
  85. find2 = True
  86. break
  87. # break again to exit loop
  88. if find2 == True:
  89. break
  90.  
  91. # We have explored the current layer, concatenate explored with currentLayer
  92. allExplored |= currentLayer
  93. # we increment the current layer to the next layer
  94. currentLayer = nextLayer.copy()
  95. # we clear the next layer to explore
  96. nextLayer.clear()
  97.  
  98. distance += 1
  99.  
  100. # if no path exists, return -1
  101. if currentLayer == set():
  102. return -1
  103.  
  104. # special case for 2x2
  105. if distance == 2:
  106. return 2
  107.  
  108. # add 1 to travel over the exit
  109. return distance + 1
  110.  
  111.  
  112. # runtime
  113. # O(1)
  114. # always checks 4 grid squares
  115. # returns a set of navigable adjacent points to some point
  116. def navigableAdjacentPoints(maze, x, y):
  117. toRet = set()
  118.  
  119. height = len(maze[0])
  120. width = len(maze)
  121.  
  122. if x != 0:
  123. if maze[x - 1][y] == 0:
  124. toRet.add((x - 1, y))
  125.  
  126. if x != width - 1:
  127. if maze[x + 1][y] == 0:
  128. toRet.add((x + 1, y))
  129.  
  130. if y != 0:
  131. if maze[x][y - 1] == 0:
  132. toRet.add((x, y - 1))
  133.  
  134. if y != height - 1:
  135. if maze[x][y + 1] == 0:
  136. toRet.add((x, y + 1))
  137.  
  138. return toRet
  139.  
  140.  
  141. # returns list of tuples [(x,y),....(x,y)] representing coordinates with walls that could be removed
  142. # walls touching halls
  143.  
  144.  
  145. # runtime
  146. # O(maze points)
  147. # O(n) , defining n as width*heigth of maze
  148.  
  149. # finds all walls worth removing in a maze
  150. # finds walls adjacent to passable space
  151. def removableWalls(maze):
  152. list_of_tuples = []
  153.  
  154. height = len(maze[0])
  155. width = len(maze)
  156.  
  157. wall = 1
  158.  
  159. for i in range(0, width):
  160. for j in range(0, height):
  161.  
  162. # if this grid is a wall
  163. if maze[i][j] == wall:
  164.  
  165. if i != 0:
  166. if maze[i - 1][j] != wall:
  167. list_of_tuples.append((i, j))
  168.  
  169. if i != (width - 1):
  170. if maze[i + 1][j] != wall:
  171. list_of_tuples.append((i, j))
  172.  
  173. if j != 0:
  174. if maze[i][j - 1] != wall:
  175. list_of_tuples.append((i, j))
  176.  
  177. if j != (height - 1):
  178. if maze[i][j + 1] != wall:
  179. list_of_tuples.append((i, j))
  180.  
  181. # remove duplicates
  182. list_of_tuples = set(list_of_tuples)
  183. list_of_tuples = list(list_of_tuples)
  184.  
  185. return list_of_tuples
  186.  
  187.  
  188. maze = [[0, 1, 1, 0], [0, 0, 0, 1], [1, 1, 0, 0], [1, 1, 1, 0]]
  189.  
  190. maze2 = [[0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1],
  191. [0, 0, 0, 0, 0, 0]]
  192.  
  193. maze3 = [[0, 1], [1, 0]]
  194.  
  195. maze4 = [[0, 0, 0, 0, 0, ],
  196. [1, 1, 1, 1, 0],
  197. [0, 0, 0, 0, 0],
  198. [0, 1, 1, 1, 1],
  199. [0, 0, 0, 0, 0]]
  200.  
  201. maze5 = [[0, 0, 0, 0, 0, 0],
  202. [1, 1, 1, 1, 1, 0],
  203. [1, 1, 1, 1, 1, 1],
  204. [0, 0, 0, 0, 0, 0],
  205. [0, 1, 1, 1, 1, 1],
  206. [0, 0, 0, 0, 0, 0]] # Answer 21
  207.  
  208. maze6 = [[0, 1, 1, 0], [0, 0, 0, 1], [1, 1, 0, 0], [1, 1, 1, 0]] # Answer 7
  209. maze7 = [[0, 1, 0, 0, 0], [0, 0, 0, 1, 0], [1, 1, 1, 1, 0]] # Answer 7
  210. maze8 = [[0, 1, 1, 1], [0, 1, 0, 0], [1, 0, 1, 0], [1, 1, 0, 0]] # Answer 7
  211. maze9 = [[0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1],
  212. [0, 0, 0, 0, 0, 0]] # Answer 11
  213.  
  214. print(answer(maze))
  215. print(answer(maze2))
  216. print(answer(maze3))
  217. print(answer(maze4))
  218. print("asd")
  219. print(answer(maze5))
  220. print(answer(maze6))
  221. print(answer(maze7))
  222. print(answer(maze8))
  223. print(answer(maze9))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement