Created
July 20, 2020 07:22
-
-
Save syminical/9c41dbfaa0c610fa6bb840acd3d5f323 to your computer and use it in GitHub Desktop.
This method calculates the shortest distance in a 2D matrix. The input matrix is a string, and the rows are separated by semi-colons.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright (C) 2020 Alexandru Manaila | |
# Python3 | |
def calculateDistance(cityMap): | |
#helpers | |
def addSpot(x, y, v): | |
#spot is valid for a path, and spot has not been visted or overlaping path is shorter. | |
if mapMatrix[y][x] == '_' and (distanceMatrix[y][x] == -1 or distanceMatrix[y][x] > v): | |
#New spot has to be checked. | |
pathStack.append((x, y)) | |
#Distance to new path updated. | |
distanceMatrix[y][x] = v | |
#environment | |
rows = cityMap.split(';') | |
mapMatrix = [[c for c in row] for row in rows] | |
nRows = len(mapMatrix) | |
nCols = len(mapMatrix[0]) | |
distanceMatrix = [[-1 for i in range(nCols)] for j in range(nRows)]; | |
officerX, officerY = -1, -1 | |
targetX, targetY = -1, -1 | |
#Find the coordinates of Officer and Target. | |
for i in range(nRows): | |
for j in range(nCols): | |
if mapMatrix[i][j] == 'O': | |
officerX, officerY = j, i | |
elif mapMatrix[i][j] == 'T': | |
targetX, targetY = j, i | |
pathStack = [(officerX, officerY)] | |
#Invalid input case, return value obtained from test case. | |
if officerX == -1 or officerY == -1 or targetX == -1 or targetY == -1: | |
return -2 | |
#Fill in distance matrix. - There is a bug here, but I don't have enough time. sorry | |
distanceMatrix[officerY][officerX] = 0 | |
while pathStack: | |
#Each iteration completes in a cell in the distance matrix. | |
#Determine new spot candidates counter-clockwise, and evaluate clockwise. | |
spot = pathStack.pop() | |
#up | |
x, y = spot[0], spot[1]-1 | |
if y > -1: | |
addSpot(x, y, distanceMatrix[spot[1]][spot[0]] + 1) | |
#left | |
x, y = spot[0]-1, spot[1] | |
if x > -1: | |
addSpot(x, y, distanceMatrix[spot[1]][spot[0]] + 1) | |
#down | |
x, y = spot[0], spot[1]+1 | |
if y < nRows: | |
addSpot(x, y, distanceMatrix[spot[1]][spot[0]] + 1) | |
#right | |
x, y = spot[0]+1, spot[1] | |
if x < nCols: | |
addSpot(x, y, distanceMatrix[spot[1]][spot[0]] + 1) | |
#Find shortest path to target. | |
#Path lengths end around T, so find smallest value from valid path spots. | |
ret = [] | |
#up | |
x, y = targetX, targetY-1 | |
#Coordinate is in bounds, and spot is not a wall. | |
if y > -1 and distanceMatrix[y][x] != -1: | |
ret.append(distanceMatrix[y][x]) | |
#left | |
x, y = targetX-1, targetY | |
if x > -1 and distanceMatrix[y][x] != -1: | |
ret.append(distanceMatrix[y][x]) | |
#down | |
x, y = targetX, targetY+1 | |
if y < nRows and distanceMatrix[y][x] != -1: | |
ret.append(distanceMatrix[y][x]) | |
#right | |
x, y = targetX+1, targetY | |
if x < nCols and distanceMatrix[y][x] != -1: | |
ret.append(distanceMatrix[y][x]) | |
if ret: | |
smallest = ret[0]; | |
for i in ret: | |
if i < smallest: | |
smallest = i | |
else: | |
#No path found, return value obtained from test case. | |
return -1 | |
print('O: ', officerX, ', ', officerY) | |
print('T: ', targetX, ', ', targetY) | |
print() | |
for row in mapMatrix: | |
print(row) | |
print() | |
for row in distanceMatrix: | |
print(row) | |
print() | |
print('ret:', ret) | |
print() | |
return smallest + 1 | |
print(calculateDistance('O__;_XT;___')) | |
print('------------------') | |
print(calculateDistance('OX_;XXT;___')) | |
print('------------------') | |
print(calculateDistance('X__;_XT;___')) | |
print('------------------') | |
print(calculateDistance('OXXX____;__XTXXX_;X_X_X___;X_____X_')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment