-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
101 lines (78 loc) · 2.61 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/**
* @param {string[][]} maze
* @returns {boolean}
*/
function canExit(maze) {
const findPosition = value =>
Object.keys(positionsMap).find(key => positionsMap[key] === value)
const getValidNeighbors = function (position) {
const [x, y] = position.split('-').map(value => Number(value))
return [`${x - 1}-${y}`, `${x + 1}-${y}`, `${x}-${y - 1}`, `${x}-${y + 1}`]
.filter(neighbor => !visitedPositions.includes(neighbor))
.filter(neighbor => [' ', 'E'].includes(positionsMap[neighbor]))
}
const positionsMap = Object.fromEntries(
maze.flatMap((row, y) => row.map((value, x) => [`${y}-${x}`, value]))
)
const startPosition = findPosition('S')
const endPosition = findPosition('E')
const visitedPositions = [startPosition]
const positionsToCheck = [startPosition]
while (positionsToCheck.length) {
const currentPosition = positionsToCheck.shift()
const validNeighbors = getValidNeighbors(currentPosition)
if (validNeighbors.includes(endPosition)) return true
validNeighbors.forEach(neighbor => {
positionsToCheck.push(neighbor)
visitedPositions.push(neighbor)
})
}
return false
}
/**
* @param {string[][]} maze
* @returns {boolean}
*/
function canExitOptimized(maze) {
const wrapMazeWithWalls = function () {
maze.forEach(row => (row.unshift('W'), row.push('W')))
const wallRow = 'W'.repeat(maze[0].length).split('')
maze.unshift(wallRow)
maze.push(wallRow)
}
const isVisitedPosition = function (x, y) {
return !visitedPositions
.filter(position => position[0] === x)
.some(position => position[1] === y)
}
const getValidNeighbors = function (x, y) {
return [
[x - 1, y],
[x + 1, y],
[x, y - 1],
[x, y + 1],
]
.filter(neighbor => isVisitedPosition(...neighbor))
.filter(neighbor => maze[neighbor[1]][neighbor[0]] !== 'W')
}
wrapMazeWithWalls()
const startY = maze.findIndex(row => row.includes('S'))
const startX = maze[startY].findIndex(cell => cell === 'S')
const startPosition = [startX, startY]
const visitedPositions = [startPosition]
const positionsToCheck = [startPosition]
let foundExit = false
while (positionsToCheck.length && !foundExit) {
const currentPosition = positionsToCheck.shift()
const validNeighbors = getValidNeighbors(...currentPosition)
validNeighbors.forEach(neighbor => {
positionsToCheck.push(neighbor)
visitedPositions.push(neighbor)
})
foundExit = validNeighbors.some(
neighbor => maze[neighbor[1]][neighbor[0]] === 'E'
)
}
return foundExit
}
export {canExit, canExitOptimized}