I'm learning algorithms and doing JavaScript exercise questions, and I don't understand how one reaches the correct answer for a particular algorithm.
The question provided in the exercise is:
Have the function CorrectPath(str) read the str parameter being passed, which will represent the movements made in a 5x5 grid of cells starting from the top left position. The characters in the input string will be entirely composed of: r, l, u, d, ?. Each of the characters stand for the direction to take within the grid, for example: r = right, l = left, u = up, d = down. Your goal is to determine what characters the question marks should be in order for a path to be created to go from the top left of the grid all the way to the bottom right without touching previously travelled on cells in the grid.
For example, the input
drdr??rrddd?
should ouptutdrdruurrdddd
I've not found a solution on my own. I'm taking a look at a solution provided, and I'm bothered because:
A. pure functions are not used to manipulate values within the CorrectPath function (note the addX()
and addY()
methods contained within). I'm not convinced the solution provided is using best practices, especially coming from a functional programming background.
B. I don't understand how the steps taken, specifically in the while
block and the succeeding for
block, are taken to reach the correct answer and why sometimes the missingLetters
array has letters remaining and other times not
The working solution provided is below
function CorrectPath(str) {
let x = 0, //start x coord
y = 0, //start y coord
missingLetters = []
const unknowns = str.match(/\W/g)
function addX() {
while(x !== 4) {
if (x > 4) {
x--;
missingLetters.push('l');
} else {
x++;
missingLetters.push('r');
}
}
}
function addY() {
while (y !== 4) {
if (y > 4) {
y--;
missingLetters.push('u');
} else {
y++;
missingLetters.push('d');
}
}
}
//tallies current number of x and y movements
for (let i=0; i<str.length; i++) {
switch (str[i]) {
case 'd':
y += 1;
break;
case 'u':
y -= 1;
break;
case 'l':
x -= 1;
break;
case 'r':
x += 1;
break;
}
}
if (x > y) { addX(); addY(); }
if (y >= x) { addY(); addX(); }
while (missingLetters.length < unknowns.length) {
var pos = missingLetters.length - 1;
if (missingLetters[pos] === 'r') {x += 1; missingLetters.push('r'); addX()}
if (missingLetters[pos] === 'l') {x -= 1; missingLetters.push('l'); addX()}
if (missingLetters[pos] === 'd') {y += 1; missingLetters.push('d'); addY()}
if (missingLetters[pos] === 'u') {y -= 1; missingLetters.push('u'); addY()}
}
var newStr = str.split('');
for (var j=0; j<str.length; j++) {
if (newStr[j] === '?') {
newStr[j] = missingLetters.shift()
}
}
return newStr.join('');
}
CorrectPath(readline());
Here's a solution I found
const dirMap = {
u: { x: 0, y: -1 },
r: { x: 1, y: 0 },
d: { x: 0, y: 1 },
l: { x: -1, y: 0 }
}
function CorrectPath(pathString) {
const map = Array(5*5)
return trace(pathString, map)
}
function trace(path, [...map], x = 0, y = 0, newPath = "") {
const steps = path.split(""),
nextMove = steps.shift()
if (nextMove === undefined) {
if (5 * y + x === (5*5-1)) return newPath
return "Bad move"
}
if (nextMove === "?") {
const moves = availableMoves(x,y,map)
if (!moves.length) return "Bad move"
for(let i = 0; i<moves.length; i++) {
let move = moves[i],
trySteps = [move,...steps].join("")
res = trace(trySteps,map,x,y,newPath)
if (!res || res === "Bad move") continue
else return res
}
return "Bad move"
} else {
if (!canMove(nextMove, x, y, map)) return "Bad move"
const pos = dirMap[nextMove],
newX = pos.x + x,
newY = pos.y + y
newPath += nextMove
map[5*newY+newX] = nextMove
return trace(steps.join(""),map,newX,newY,newPath)
}
}
function availableMoves(x,y,map) {
const steps = []
Object.keys(dirMap).forEach(z => {
if (canMove(z,x,y,map)) steps.push(z)
})
return steps
}
function canMove(dir, xPath, yPath, map) {
const pos = dirMap[dir],
x = pos.x + xPath,
y = pos.y + yPath
if (x > 4 || x < 0 || y > 4 || y < 0) return false
if (map[5*y+x] !== undefined) return false
return true
}
CorrectPath(readline());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.