Advertisement
Guest User

Untitled

a guest
Jan 20th, 2020
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.69 KB | None | 0 0
  1. from heapq import heappush, heappop
  2. from typing import List
  3.  
  4. # See utils library for canonical version
  5. def dijkstra(source, getNbr, isDest=None):
  6.     dest = None
  7.     dist = {}
  8.     queue = []
  9.     heappush(queue, (0, source))
  10.     while queue:
  11.         # Grab current shortest that isn't finalized yet
  12.         minDist, minNode = heappop(queue)
  13.         if minNode in dist:
  14.             # Finalized with something shorter before, continue
  15.             assert dist[minNode] <= minDist
  16.             continue
  17.         # Finalize the current shortest
  18.         dist[minNode] = minDist
  19.         # Check if it's already at the destination
  20.         if isDest and isDest(minNode):
  21.             dest = minNode
  22.             break
  23.         # Add all neighbors that still needs to be processed
  24.         for nbr, weight in getNbr(minNode):
  25.             if nbr not in dist:
  26.                 heappush(queue, (minDist + weight, nbr))
  27.             else:
  28.                 assert minDist + weight >= dist[nbr]
  29.     return dist, dest
  30.  
  31.  
  32. dirs = [(-1, 0), (0, -1), (0, 1), (1, 0)]
  33.  
  34.  
  35. class Solution:
  36.     def minPushBox(self, grid: List[List[str]]) -> int:
  37.         """Move box one step at a time.
  38.        For each step check if player can move opposite of where you want the box to go.
  39.        Implementation is wasteful because I thought we were optimizing for player moves too"""
  40.         R = len(grid)
  41.         C = len(grid[0])
  42.         boxStart = None
  43.         playerStart = None
  44.         boxEnd = None
  45.         for r in range(R):
  46.             for c in range(C):
  47.                 if grid[r][c] == "B":
  48.                     boxStart = (r, c)
  49.                     grid[r][c] = "."
  50.                 if grid[r][c] == "S":
  51.                     playerStart = (r, c)
  52.                     grid[r][c] = "."
  53.                 if grid[r][c] == "T":
  54.                     boxEnd = (r, c)
  55.                     grid[r][c] = "."
  56.  
  57.         def getWalkingDist(startR, startC, endR, endC, obstacles):
  58.             def getPlayerNbr(node):
  59.                 ret = []
  60.                 r, c = node  # player position
  61.                 for dr, dc in dirs:
  62.                     nr = r + dr
  63.                     nc = c + dc
  64.                     if (
  65.                         0 <= nr < R
  66.                         and 0 <= nc < C
  67.                         and grid[nr][nc] == "."
  68.                         and (nr, nc) not in obstacles
  69.                     ):
  70.                         ret.append(((nr, nc), 1))
  71.                 return ret
  72.  
  73.             dist, dest = dijkstra(
  74.                 (startR, startC), getPlayerNbr, lambda node: node == (endR, endC)
  75.             )
  76.             if dest in dist:
  77.                 return dist[dest]
  78.             else:
  79.                 return float("inf")
  80.  
  81.         def getBoxNbr(node):
  82.             ret = []
  83.             boxR, boxC, playerR, playerC = node
  84.  
  85.             for dr, dc in dirs:
  86.                 boxNr = boxR + dr
  87.                 boxNc = boxC + dc
  88.                 playerNr = boxR - dr
  89.                 playerNc = boxC - dc
  90.                 if (
  91.                     0 <= boxNr < R
  92.                     and 0 <= boxNc < C
  93.                     and 0 <= playerNr < R
  94.                     and 0 <= playerNc < C
  95.                     and grid[boxNr][boxNc] == "."
  96.                     and grid[playerNr][playerNc] == "."
  97.                 ):
  98.                     dist = getWalkingDist(
  99.                         playerR, playerC, playerNr, playerNc, [(boxR, boxC)]
  100.                     )
  101.                     if dist != float("inf"):
  102.                         ret.append(((boxNr, boxNc, boxR, boxC), 1))
  103.             return ret
  104.  
  105.         dist, dest = dijkstra(
  106.             (*boxStart, *playerStart), getBoxNbr, lambda node: node[:2] == boxEnd
  107.         )
  108.  
  109.         if dest in dist:
  110.             return dist[dest]
  111.         return -1
  112.  
  113.  
  114. if __name__ == "__main__":
  115.     assert (
  116.         Solution().minPushBox(
  117.             [
  118.                 ["#", "#", "#", "#", "#", "#"],
  119.                 ["#", "T", "#", "#", "#", "#"],
  120.                 ["#", ".", ".", "B", ".", "#"],
  121.                 ["#", ".", "#", "#", ".", "#"],
  122.                 ["#", ".", ".", ".", "S", "#"],
  123.                 ["#", "#", "#", "#", "#", "#"],
  124.             ]
  125.         )
  126.         == 3
  127.     )
  128.  
  129.     assert (
  130.         Solution().minPushBox(
  131.             [
  132.                 ["#", "#", "#", "#", "#", "#"],
  133.                 ["#", "T", "#", "#", "#", "#"],
  134.                 ["#", ".", ".", "B", ".", "#"],
  135.                 ["#", "#", "#", "#", ".", "#"],
  136.                 ["#", ".", ".", ".", "S", "#"],
  137.                 ["#", "#", "#", "#", "#", "#"],
  138.             ]
  139.         )
  140.         == -1
  141.     )
  142.  
  143.     assert (
  144.         Solution().minPushBox(
  145.             [
  146.                 ["#", "#", "#", "#", "#", "#"],
  147.                 ["#", "T", ".", ".", "#", "#"],
  148.                 ["#", ".", "#", "B", ".", "#"],
  149.                 ["#", ".", ".", ".", ".", "#"],
  150.                 ["#", ".", ".", ".", "S", "#"],
  151.                 ["#", "#", "#", "#", "#", "#"],
  152.             ]
  153.         )
  154.         == 5
  155.     )
  156.  
  157.     assert (
  158.         Solution().minPushBox(
  159.             [
  160.                 ["#", "#", "#", "#", "#", "#", "#"],
  161.                 ["#", "S", "#", ".", "B", "T", "#"],
  162.                 ["#", "#", "#", "#", "#", "#", "#"],
  163.             ]
  164.         )
  165.         == -1
  166.     )
  167.     assert (
  168.         Solution().minPushBox(
  169.             [
  170.                 ["#", ".", ".", "#", "#", "#", "#", "#"],
  171.                 ["#", ".", ".", "T", "#", ".", ".", "#"],
  172.                 ["#", ".", ".", ".", "#", "B", ".", "#"],
  173.                 ["#", ".", ".", ".", ".", ".", ".", "#"],
  174.                 ["#", ".", ".", ".", "#", ".", "S", "#"],
  175.                 ["#", ".", ".", "#", "#", "#", "#", "#"],
  176.             ]
  177.         )
  178.         == 7
  179.     )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement