练习

测量机器人

很难通过让机器人解决一些场景来客观比较他们。 也许一个机器人碰巧得到了更简单的任务,或者它擅长的那种任务,而另一个没有。

编写一个compareRobots,接受两个机器人(和它们的起始记忆)。 它应该生成 100 个任务,并让每个机器人解决每个这些任务。 完成后,它应输出每个机器人每个任务的平均步数。

为了公平起见,请确保你将每个任务分配给两个机器人,而不是为每个机器人生成不同的任务。

  1. function compareRobots(robot1, memory1, robot2, memory2) {
  2. // Your code here
  3. }
  4. compareRobots(routeRobot, [], goalOrientedRobot, []);

机器人的效率

你能写一个机器人,比goalOrientedRobot更快完成递送任务吗? 如果你观察机器人的行为,它会做什么明显愚蠢的事情?如何改进它们?

如果你解决了上一个练习,你可能打算使用compareRobots函数来验证你是否改进了机器人。

  1. // Your code here
  2. runRobotAnimation(VillageState.random(), yourRobot, memory);

持久性分组

标准 JavaScript 环境中提供的大多数数据结构不太适合持久使用。 数组有sliceconcat方法,可以让我们轻松创建新的数组而不会损坏旧数组。 但是Set没有添加或删除项目并创建新集合的方法。

编写一个新的类PGroup,类似于第六章中的Group类,它存储一组值。 像Group一样,它具有adddeletehas方法。

然而,它的add方法应该返回一个新的PGroup实例,并添加给定的成员,并保持旧的不变。 与之类似,delete创建一个没有给定成员的新实例。

该类应该适用于任何类型的值,而不仅仅是字符串。 当与大量值一起使用时,它不一定非常高效。

构造函数不应该是类接口的一部分(尽管你绝对会打算在内部使用它)。 相反,有一个空的实例PGroup.empty,可用作起始值。

为什么只需要一个PGroup.empty值,而不是每次都创建一个新的空分组?

  1. class PGroup {
  2. // Your code here
  3. }
  4. let a = PGroup.empty.add("a");
  5. let ab = a.add("b");
  6. let b = ab.delete("a");
  7. console.log(b.has("b"));
  8. // → true
  9. console.log(a.has("b"));
  10. // → false
  11. console.log(b.has("a"));
  12. // → false