简体   繁体   中英

JavaScript method to determine correct path is confusing

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 ouptut drdruurrdddd

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM