JavaScript - 十分钟散步计划 - 如何正确访问数组元素

3
如果您不熟悉这个挑战,请看以下说明:

https://www.codewars.com/kata/54da539698b8a2ad76000228/train/javascript

你住在卡尔特西亚市,那里的所有道路都是按照完美的网格布局排列的。你提前了十分钟到达约定地点,于是决定趁机去散步。该城市为其居民提供了一款名为“步行生成应用程序”的手机应用程序——每次按下按钮,它会向您发送一个由表示行走方向的单个字母字符串组成的数组(例如['n','s','w','e'])。您总是只向一个方向行走一个街区,并且您知道每穿过一个城市街区需要一分钟,因此请编写一个函数,如果应用程序给出的步行路线恰好需要十分钟(您不想早到或晚到!)并且当然能将您带回起点,则返回true。否则返回false。

到目前为止,我尝试了:

function isValidWalk(walk) {

  //initiate person starting point
  let person = [0, 0]
  //establish what the ending point must be
  let finalDestination = [0, 0]

  let north = [0, 1]
  let east = [1, 0]
  let south = [0, -1]
  let west = [-1, 0]

  //as long as the length of the array is 10 or less, continue walk
  for (let i = 0; i <= 10; i++) {
    //if the letter in the array is "n", move north
    if (walk[i] === "n") {
      person + north;
    }
    //if the letter in the array is "e", move east
    if (walk[i] === "e") {
      person + east;
    }
    //if the letter in the array is "s", move south
    if (walk[i] === "s") {
      person + south;
    }
    //if the letter in the array is "w", move west
    if (walk[i] === "w") {
      person + west;
    }
  }

  if (person === finalDestination) {
    return true;
  }
  else {
    return false;
  }

}

这段代码通过了6/9个测试,但对于有效的步行路线没有返回true
如您所见,我试图表达isValidWalk函数应该在person的位置在步行结束时等于finalDestination变量时返回true。
我知道可能有其他解决问题的方法,但如果可能的话,我想继续遵循我已经建立的逻辑。
我想知道我的问题是否是我没有正确访问数组中的元素?即这里是否正确获取了数组元素:walk[i]
    if (walk[i] === "n") {
      person + north;
    }

这就是应该在这个想象的网格中移动“person”的内容,但显然它什么也没做。我应该尝试哪些其他语法来访问数组中的元素并检查它们是否等于“n”、“e”、“s”和“w”?

1
他们没有说Cartesia在哪个表面上,但是假设它是一个平面,就不需要操作坐标,只需确保字符串中"N"和"S"的数量相等,"E"和"W"的数量也相等。 - georg
2个回答

5

首先,JavaScript数组不像数学矩阵那样工作。array1 + array2不会将这些数组中的各个值相加。相反,您需要增加/减少数组内的值:

if (walk[i] === "n") {
  person[0]++;
}
if (walk[i] === "e") {
  person[1]++;
}
if (walk[i] === "s") {
  person[0]--;
}
if (walk[i] === "w") {
  person[1]--;
}

更简洁地说:
switch(walk[i]) {
  case "n": person[0]++; break;
  case "e": person[1]++; break;
  case "s": person[0]--; break;
  case "w": person[1]--; break;
}

其次,personfinalDestination 都是数组,因此 === 表示引用相等。也就是说,只有当两个变量在内存中指向同一个位置时,person === finalDestination 才会返回 true。相反,你需要比较数组中的每个值,例如:

if (person[0] === finalDestination[0] &&
    person[1] === finalDestination[1]) {
  return true;
}
else {
  return false;
}

更简洁地说:
return person[0] === finalDestination[0] &&
       person[1] === finalDestination[1];

注意,finalDestination 永远不会改变,因此实际上您根本不需要该变量。您可以将其替换为:

return person[0] === 0 && person[1] === 0;

关于需求的最后一点:

如果你要走的路程正好需要十分钟,则返回true

你需要在函数顶部添加以下内容:

if (walk.length !== 10) return false;

为了让代码更简洁,确保你的 for 循环不要超过 walk 的结尾。可以将 i <= 10 替换为 i < 10i < walk.length

我看到定义那些变量 - north, south, eastwest - 基本上是没有意义的? - HappyHands31
1
@HappyHands31 在这种情况下它们并不是必要的。如果你想要表示更复杂的方向(例如对角线或象棋中马的移动),实现一种向量/矩阵数学可能是值得的。 - p.s.w.g
1
@HappyHands31 不是很对,我会称之为干净的代码,如果它变得更加复杂(更多方向、对角线等),那么这种模式可能会让你走得更远。 - Jonas Wilms
是的,当步行时间不完全是十分钟时,我仍然会遇到错误。感谢您解决这个问题,并提到将“<=”更改为“<”这一点 - 谢谢。 - HappyHands31

2

你不能简单地将数组相加。如果这样做,它们会被转换为字符串,而且你也没有在任何地方存储结果:

最初的回答:

[0, 1] + [0, 0]
// equals
"0,1" + "0,0"

你需要逐个数值相加:
person[0] += west[0];
person[1] += west[1];

此外,通过引用比较这些数组如下:

最初的回答:另外,在这里通过引用比较这些数组:
 if (person === finalDestination) {

只有当你执行person = finalDestination时,它才会为true。你可能想再次逐个比较它们的值: "person" 和 "finalDestination"。最初的回答。
 if(person[0] === finalDestination[0] && person[1] ===  finalDestination[1])

话虽如此,虽然这样做是可行的,但有更简单的解决方案(提示:分而治之:南/北和西/东),如果您解决了该题目,您将会看到这些解决方案 :)

这样可以通过6/9个测试

一个错误的时钟一天也会正确两次。如果你这样做:

Original Answer翻译成"最初的回答"

 return Math.random() > 0.5;

"最初的回答":平均而言,经过500次尝试后它也能正常工作。我的观点是:通过测试用例的数量并不能真正反映出你的解决方案有多少错误,这只是给下一个 Kata 的小提示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接