乐趣区

关于前端:JS-教练我想做习题18

???? 前言

大家好呀,我是毛小悠,能够叫我二毛,在家中排行老二,是一名前端开发工程师。

本系列文章旨在通过练习来进步 JavaScript 的能力,一起欢快的做题吧。????????????

以下每道题,二毛我都有尝试做一遍。倡议限时训练,比方限定为半小时,如果半小时内想不进去,能够联合文章开端的参考答案来思考。

能够在下方评论区留言或者加我的微信:code\_maomao。期待你的到来。

求关注求点赞 ????\~~~????????????

???? 题目 1:单词搜寻难题挑战

单词搜寻是经典的儿童拼图游戏,您须要在其中找到程度、垂直或对角线暗藏在随机字母网格中的单词列表。

单词“dog”,“cat”和“parrot”都暗藏在上面的单词搜寻拼图网格中。

    A B C D E F G H 

1   F H K E F F H D
2   F D O G I O P V
3   F J D K O I A Q
4   F J E I H Q R M
5   C W B X X N R I
6   A A E S F U O F
7   C U T H E S T U
8   F J J S N J I O

参数:

零碎会为您提供单词列表:[‘DOG’,’CAT’,’PARROT’] 和代表方形字母网格的字符串:’FHKEFFHDFDOGIOPVFJDKOIAQFJEIHQRMUWTXXNRIAAESFUOFCUHHESTUFJJSNJIO’。

拼图字符串全副大写,并且不蕴含空格或网格题目(例如,在下面的可视示例中,列 A - H 和行 1 -8)。

单词只会在程度,垂直或对角线的左右方向上拼写。

假如网格拼图将始终是一个现实的正方形,最小尺寸为 4 ×4,最大尺寸为 26×26(A- Z 列)。

您的挑战:

您必须返回一个数组的子数组,该数组代表每个单词的每个字母的网格地位。行用数字示意。列用字母示意。

在下面的示例中,解决方案为:[[B2,C2,D2],[A5,B6,C7,],[G2,G3,G4,G5,G6,G7]]

如果在拼图中找不到单词,则其地位子数组应显示为 [‘ 找不到单词。’]。例如:

[[B2,C2,D2],[‘ 找不到单词。],[G2,G3,G4,G5,G6,G7]]]

您能够假如任何一个谜题中都不会暗藏反复的单词。

习题代码:

function wordSearch(words, puzzle) {// your code goes here.}

答案

???? 题目 1 的答案

参考答案 1:

function wordSearch(words, puzzle) {var s=Math.sqrt(puzzle.length), m = puzzle.match(new RegExp(`.{${s}}`,'g'));
  return words.map(w=>{for(let j=0; j<s; j++) for(let i=0; i<s; i++) {
      var r=true, d=true, v=true;
      if(i+w.length<=s) {for(let k=0; k<w.length; k++) if(m[j][i+k]!==w[k]) r=false;
        if(r) return [...Array(w.length)].map((_,k)=>[i+k,j]);
      }
      if(j+w.length<=s) {for(let k=0; k<w.length; k++) if(m[j+k][i]!==w[k]) d=false;
        if(d) return [...Array(w.length)].map((_,k)=>[i,j+k]);
      }
      if(i+w.length<=s&&j+w.length<=s) {for(let k=0; k<w.length; k++) if(m[j+k][i+k]!==w[k]) v=false;
        if(v) return [...Array(w.length)].map((_,k)=>[i+k,j+k]);
      }
    }
    return -1;
  }).map(r=>r===-1?['Word not found.']:r.map(([i,j])=>'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[i]+(j+1)));
}

参考答案 2:

function buildGrid(puzzle, sideSize) {const regex = new RegExp(`[A-Z]{${sideSize}}`, 'g');
  return puzzle.match(regex);
}

function buildCoords(sideSize) {
  const alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  const letters = [...alpha.slice(0, sideSize)];
  
  let coords = [];
  
  for (let num = 1; num <= sideSize; num++) {let row = letters.map(letter => letter + String(num));
    coords.push(row);
  }
  
  return coords;
}

function getCols(grid) {return [...grid[0]].map((_, colIdx) => {return grid.map(row => row[colIdx])
               .join('');
  });
}

function getDiagonals(rows) {rows = rows.map(row => [...row]);
  
  const sideSize = rows.length;
  let shiftFromLast = true;
  let rowCounts = [];
  
  for (let count = 1; count < sideSize; count++) {rowCounts.push(count);
  }
  
  for (let count = sideSize; count >= 1; count--) {rowCounts.push(count);
  }
  
  const diagonals = rowCounts.map(rowCount => {let targetRows = shiftFromLast ? rows.slice(-rowCount) : rows.slice(0, rowCount);
    if (rowCount === sideSize) shiftFromLast = false;
    let diagonal = targetRows.map(row => row.shift());//.join('');
    return diagonal;
  });
  
  return diagonals;
}

function getGridDiagonals(grid) {let rows = grid.map(rowStr => [...rowStr]);
  return getDiagonals(rows);
}

function getCoordDiagonals(gridCoords) {return getDiagonals(gridCoords);
} 

function searchRows(grid, gridCoords, word) {const targetRow = grid.findIndex(row => row.includes(word));
  
  if (targetRow !== -1) {let wordStart = grid[targetRow].search(word);
    let wordStop = wordStart + word.length;
    return gridCoords[targetRow].slice(wordStart, wordStop);
  } else {return null;}
}

function searchCols(grid, gridCoords, word) {const gridCols = getCols(grid);
  const coordCols = [...grid[0]].map((_, colIdx) => {return gridCoords.map(row => row[colIdx]);
  });
  
  const targetCol = gridCols.findIndex(col => col.includes(word));
  
  if (targetCol !== -1) {let wordStart = gridCols[targetCol].search(word);
    let wordStop = wordStart + word.length;
    return coordCols[targetCol].slice(wordStart, wordStop);
  } else {return null;}
}

function searchDiagonals(grid, gridCoords, word) {const gridDiagonals = getGridDiagonals(grid);
  const coordDiagonals = getCoordDiagonals(gridCoords);
  
  const targetDiagonal = gridDiagonals.map(diagonal => diagonal.join(''))
                                      .findIndex(diagonal => diagonal.includes(word));
  
  if (targetDiagonal !== -1) {let wordStart = gridDiagonals[targetDiagonal].join('').search(word);
    let wordStop = wordStart + word.length;
    return coordDiagonals[targetDiagonal].slice(wordStart, wordStop);
  } else {return null;}
}

function wordSearch(words, puzzle) {const sideSize = Math.sqrt(puzzle.length);
  const grid = buildGrid(puzzle, sideSize);
  const gridCoords = buildCoords(sideSize);
  
  const letterCoords = words.map (word => {if (searchRows(grid, gridCoords, word) !== null) {return searchRows(grid, gridCoords, word);
    } else if (searchCols(grid, gridCoords, word) !== null) {return searchCols(grid, gridCoords, word);
    } else if (searchDiagonals(grid, gridCoords, word) !== null) {return searchDiagonals(grid, gridCoords, word);
    } else {return ['Word not found.'];
    }
  });
  
  return letterCoords;
}

参考答案 3:

// Approach:
//
// Create a tree of all potential paths for a given word and pick first path
//  that has all letters traveling in same direction.
// Paths can go east ("across"), south ("down") or southeast ("diagonal").
// First level of tree is the first letter of the word, anywhere in the puzzle.
// Continue building tree from there, one letter of the word at a time.

// Main Program
function wordSearch(words, puzzle) {const grid = new Grid(puzzle);
  grid.init();
  return words.map((word) => {return grid.search(word);
  });
}

// Classes and helper functions

class Node {constructor(letter, x, y, parent, direction) {
    this.letter = letter;
    this.x = x;
    this.y = y;
    this.parent = parent;
    this.direction = direction;
  }
}

class Grid {constructor(puzzle) {this.size = Math.sqrt(puzzle.length);
    this.puzzle = puzzle;
    this.grid = [];
    this.showPuzzle();}

  init() {
    const size = this.size;
    for (let i = 0; i < size; i++) {this.grid.push(this.puzzle.substring(i * size, i * size + size));
    }
  }
  
  showPuzzle() {
    let topLabel = '';
    for (let i = 0; i < this.size; i++) {topLabel += String.fromCharCode(65 + i);
    }
    console.log(' ', topLabel);

    for (let i = 0; i < this.size; i++) {
      let rowLabel = '';
      if (i+1 < 10) {rowLabel = ` ${i+1}`;
      } else {rowLabel = `${i+1}`;
      }
      console.log(rowLabel, this.puzzle.substring(i * this.size, i * this.size + this.size));
    }
    console.log();}
  
  search(word) {
    // create a tree with root node that points to all first letters of the word
    // search for 2nd letter to east, south and south-east
    // continue until word is done
    // follow the leaf note back to the root to find the path
    
    console.log(`Searching for '${word}'...`);

    const rootNode = new Node();
    let leafNodesQueue = [];
    
    // find all the first letters
    const firstLetter = word[0];
    for (let x = 0; x < this.size; x++) {for (let y = 0; y < this.size; y++) {if (this.grid[y][x] === firstLetter) {const node = new Node(firstLetter, x, y, root);
          leafNodesQueue.push(node);
        }
      }
    }
    
    // loop from 2nd letter to end of the word
    for (let i = 1; i < word.length; i++) {const newLeafs = [];
      
      if (leafNodesQueue.length === 0) {
        // short circuit, word not found
        break;
      }

      // loop through all the leaf nodes
      // discover if next letter is east, south or southeast
      while (leafNodesQueue.length) {const leaf = leafNodesQueue.pop();
        const {x, y} = leaf;
        if (x < this.size - 1 && this.grid[y][x + 1] === word[i]) {const node = new Node(word[i], x + 1, y, leaf, 'east');
          newLeafs.push(node);
        }
        if (y < this.size - 1 && this.grid[y + 1][x] === word[i]) {const node = new Node(word[i], x, y + 1, leaf, 'south');
          newLeafs.push(node);
        }
        if (x < this.size - 1 && y < this.size - 1 && this.grid[y + 1][x + 1] === word[i]) {const node = new Node(word[i], x + 1, y + 1, leaf, 'southeast');
          newLeafs.push(node);
        }
      } // end while
      leafNodesQueue = newLeafs;
    }

    // ensure we only capture paths where letters are all going in one direction
    const validResults = [];
    while (leafNodesQueue.length) {let result = [];
      const leaf = leafNodesQueue.pop();
      findPath(leaf, result);
      const officialDirection = result[0].direction;
      let ok = true;
      for (let i = result.length - 2; i > 0; i--) {if (result[i].direction !== officialDirection) {ok = false;}
      }
      if (ok) {validResults.push(result);
        break; // only need one valid result
      }
    }

    // if we have at least one solution, grab first one
    if (validResults.length) {return validResults[0].reverse().map((node) => {return node.location;});
    }

    return ['Word not found.'];
  }
}

function findPath(node, result) {if (node === undefined) {return;}
  // only push on nodes that have letters (to skip adding root node)
  if (node.letter) {result.push({ direction: node.direction, location: `${String.fromCharCode(65 + node.x)}${node.y+1}`, letter: node.letter });
  }
  return findPath(node.parent, result);
}

参考答案 4:

function wordSearch(words, puzzle) {const position = []
const arr = puzzle.split('')
const gridLenght = Math.pow(arr.length, 0.5)
// create Grid.
const gridHoriz = arr.reduce(function(result, value, index, array) {if (index % gridLenght === 0)
    result.push(array.slice(index, index + gridLenght));
  return result;
}, []);
const gridVert = []
for(let i = 0; i< gridHoriz.length; i++) {const line = []
  for(let j = 0; j < gridHoriz.length; j ++) {line.push(gridHoriz[j][i])
  }  
  gridVert.push(line)
}
const diagonal = (array) => {
  const gridLength = array.length
  const rowLength = array[0].length
  const maxLength = Math.max(rowLength, gridLength)
  
  const gridDiag = []
 
  for(let i = 0; i <= 2 * (maxLength - 1) ; ++i){let temp = [] 
    for(let j = gridLength - 1; j >=0; --j) {const foo = i - (gridLength - j)
      if(foo >= 0 && i - (gridLength - j) < rowLength) {temp.push(array[j][foo])
      }
    }
     if(temp.length > 0) {gridDiag.push(temp.reverse())
     }
  }

  return gridDiag
} 
const gridDiagonal = diagonal(gridHoriz)
const addPosition = (grid, gridName) => {return grid.map((row, rowIndex) => {return row.map( (letter, letterIndex) => {const alphabet = (gridName === 'gridVert') ? String.fromCharCode(rowIndex+1 + 64) : String.fromCharCode(letterIndex+1 + 64)
         const obj ={}
         const position = (gridName === 'gridVert') ? `${alphabet}${letterIndex + 1}` : `${alphabet}${rowIndex + 1}`
         obj[position]  = letter
          return obj
    })
  })
}
const gridHorizPosition = addPosition(gridHoriz, 'gridHoriz')
const gridVertPosition = addPosition(gridVert,'gridVert')
const gridDiagonalPosition = diagonal(gridHorizPosition)


const gridMaster = [gridDiagonal, gridVert, gridHoriz]
const gridMasterPosition = [gridDiagonalPosition, gridVertPosition, gridHorizPosition]


words.map((word, index) => {const temp = []
  for(let i =0 ; i < gridMaster.length; i++){for(let j = 0; j < gridMaster[i].length; j++) {const string = gridMaster[i][j].join('')
      if(string.includes(word)) {const wordStart = string.search(word)
      const rowPosition = gridMaster[i].indexOf(gridMaster[i][j])
        for(let f = 0 ; f < word.length; f++) {const coordinate = Object.keys(gridMasterPosition[i][rowPosition][wordStart + f])[0]
          temp.push(coordinate)
        }
      } 
    }
  }
  
  (temp.length > 0) ? position.push(temp) : position.push(['Word not found.'])
})


return position

}

参考答案 5:

function wordSearch(words, puzzle) {function horizontal(word) {for (let row = 0; row < side; row++) {const pos = puzzleH[row].indexOf(word)

      if (pos !== -1) {const answer = []
        const row2 = row + 1

        for (let i = 0, len = word.length; i < len; i++) {answer.push(String.fromCharCode((pos + i) + A) + row2)
        }        
        
        return answer
      }
    }

    return []}

  function vertical(word) {for (let col = 0; col < side; col++) {const pos = puzzleV[col].indexOf(word)

      if (pos !== -1) {const answer = []
        const col2 = String.fromCharCode(col + A)

        for (let i = 0, len = word.length; i < len; i++) {answer.push(col2 + (pos + 1 + i))
        }        
        
        return answer
      }
    }

    return []}

  function diagonal(word) {
    const len = word.length
    const max = side - len

    let found = false
    let foundRow = -1
    let foundCol = -1

    for (let col = 0; col <= max; col++) {
      let s = "";

      for (let col2 = col; col2 < side; col2++) {s += puzzleH[col2 - col][col2]
      }

      let pos = s.indexOf(word)

      if (pos !== -1) {
        found = true
        foundRow = pos + 1
        foundCol = col + pos
        break
      }
    }

    for (let row = 1; row <= max; row++) {
      let s = "";

      for (let row2 = row; row2 < side; row2++) {s += puzzleH[row2][row2 - row]
      }

      let pos = s.indexOf(word)

      if (pos !== -1) {
        found = true
        foundRow = row + pos + 1
        foundCol = pos
        break
      }
    }   
        
    let answer = []

    if (found) {for (let i = 0; i < len; i++) {answer.push(String.fromCharCode((foundCol + i) + A) + (foundRow + i))
      }
    }

    return answer
  }

  const side = Math.sqrt(puzzle.length)
  const puzzleArray =puzzle.split('')
  const puzzleH =[...Array(side).keys()].map(row => {
    const start = row * side;
    return puzzleArray.slice(start, start + side).join('')
    })
  const puzzleV =[...Array(side).keys()].map(col => puzzleArray.filter((letter, i) => i % side === col).join(''))
  const A = 'A'.charCodeAt(0)
  // console.log(puzzleH)
  // console.log(puzzleV)

  const results = []

  for (const word of words) {
    let found = false
    const hres = horizontal(word)

    if (hres.length > 0) {
      found = true
      results.push(hres)
    }

    const vres = vertical(word)

    if (vres.length > 0) {
      found = true
      results.push(vres)
    }
    
    const dres = diagonal(word)

    if (dres.length > 0) {
      found = true
      results.push(dres)
    }
    
    if (!found) {results.push(['Word not found.'])
    }
  }
  
  return results
}

???? 后序

本系列会定期更新的,题目会由浅到深的逐步提高。

求关注求点赞 ????~~????????????

能够关注我的公众号: 前端毛小悠 。欢送浏览

退出移动版