Skip to content

Commit 5a7f881

Browse files
committed
Integrate copyediting for chapter 7
1 parent e53a20a commit 5a7f881

File tree

1 file changed

+19
-25
lines changed

1 file changed

+19
-25
lines changed

07_robot.md

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
{{quote {author: "Edsger Dijkstra", title: "The Threats to Computing Science", chapter: true}
66

7-
[...] the question of whether Machines Can Think [...] is about as relevant as the question of whether Submarines Can Swim.
7+
The question of whether Machines Can Think [...] is about as relevant as the question of whether Submarines Can Swim.
88

99
quote}}
1010

@@ -64,15 +64,13 @@ function buildGraph(edges) {
6464
const roadGraph = buildGraph(roads);
6565
```
6666

67-
Given an array of edges, `buildGraph` creates a map object that, for each node, stores an array of connected nodes.
68-
6967
{{index "split method"}}
7068

71-
It uses the `split` method to go from the road strings, which have the form `"Start-End"`, to two-element arrays containing the start and end as separate strings.
69+
Given an array of edges, `buildGraph` creates a map object that, for each node, stores an array of connected nodes. It uses the `split` method to go from the road stringswhich have the form `"Start-End"`)—to two-element arrays containing the start and end as separate strings.
7270

7371
## The task
7472

75-
Our ((robot)) will be moving around the village. There are parcels in various places, each addressed to some other place. The robot picks up parcels when it comes to them and delivers them when it arrives at their destinations.
73+
Our ((robot)) will be moving around the village. There are parcels in various places, each addressed to some other place. The robot picks up parcels when it comes across them and delivers them when it arrives at their destinations.
7674

7775
The automaton must decide, at each point, where to go next. It has finished its task when all parcels have been delivered.
7876

@@ -92,7 +90,7 @@ Instead, let's condense the village's state down to the minimal set of values th
9290

9391
{{index "VillageState class", "persistent data structure"}}
9492

95-
And while we're at it, let's make it so that we don't _change_ this state when the robot moves but rather compute a _new_ state for the situation after the move.
93+
While we're at it, let's make it so that we don't _change_ this state when the robot moves but rather compute a _new_ state for the situation after the move.
9694

9795
```{includeCode: true}
9896
class VillageState {
@@ -119,7 +117,7 @@ The `move` method is where the action happens. It first checks whether there is
119117

120118
{{index "map method", "filter method"}}
121119

122-
Then it creates a new state with the destination as the robot's new place. But it also needs to create a new set of parcels—parcels that the robot is carrying (that are at the robot's current place) need to be moved along to the new place. And parcels that are addressed to the new place need to be delivered—that is, they need to be removed from the set of undelivered parcels. The call to `map` takes care of the moving, and the call to `filter` does the delivering.
120+
Next, the method creates a new state with the destination as the robot's new place. It also needs to create a new set of parcels—parcels that the robot is carrying (that are at the robot's current place) need to be moved along to the new place. And parcels that are addressed to the new place need to be delivered—that is, they need to be removed from the set of undelivered parcels. The call to `map` takes care of the moving, and the call to `filter` does the delivering.
123121

124122
Parcel objects aren't changed when they are moved but re-created. The `move` method gives us a new village state but leaves the old one entirely intact.
125123

@@ -138,15 +136,15 @@ console.log(first.place);
138136
// → Post Office
139137
```
140138

141-
The move causes the parcel to be delivered, and this is reflected in the next state. But the initial state still describes the situation where the robot is at the post office and the parcel is undelivered.
139+
The move causes the parcel to be delivered, which is reflected in the next state. But the initial state still describes the situation where the robot is at the post office and the parcel is undelivered.
142140

143141
## Persistent data
144142

145143
{{index "persistent data structure", mutability, ["data structure", immutable]}}
146144

147145
Data structures that don't change are called _((immutable))_ or _persistent_. They behave a lot like strings and numbers in that they are who they are and stay that way, rather than containing different things at different times.
148146

149-
In JavaScript, just about everything _can_ be changed, so working with values that are supposed to be persistent requires some restraint. There is a function called `Object.freeze` that changes an object so that writing to its properties is ignored. You could use that to make sure your objects aren't changed, if you want to be careful. Freezing does require the computer to do some extra work, and having updates ignored is just about as likely to confuse someone as having them do the wrong thing. So I usually prefer to just tell people that a given object shouldn't be messed with and hope they remember it.
147+
In JavaScript, just about everything _can_ be changed, so working with values that are supposed to be persistent requires some restraint. There is a function called `Object.freeze` that changes an object so that writing to its properties is ignored. You could use that to make sure your objects aren't changed, if you want to be careful. Freezing does require the computer to do some extra work, and having updates ignored is just about as likely to confuse someone as having them do the wrong thing. I usually prefer to just tell people that a given object shouldn't be messed with and hope they remember it.
150148

151149
```
152150
let object = Object.freeze({value: 5});
@@ -155,9 +153,7 @@ console.log(object.value);
155153
// → 5
156154
```
157155

158-
Why am I going out of my way to not change objects when the language is obviously expecting me to?
159-
160-
Because it helps me understand my programs. This is about complexity management again. When the objects in my system are fixed, stable things, I can consider operations on them in isolation—moving to Alice's house from a given start state always produces the same new state. When objects change over time, that adds a whole new dimension of complexity to this kind of reasoning.
156+
Why am I going out of my way to not change objects when the language is obviously expecting me to? Because it helps me understand my programs. This is about complexity management again. When the objects in my system are fixed, stable things, I can consider operations on them in isolation—moving to Alice's house from a given start state always produces the same new state. When objects change over time, that adds a whole new dimension of complexity to this kind of reasoning.
161157

162158
For a small system like the one we are building in this chapter, we could handle that bit of extra complexity. But the most important limit on what kind of systems we can build is how much we can understand. Anything that makes your code easier to understand makes it possible to build a more ambitious system.
163159

@@ -171,7 +167,7 @@ A delivery ((robot)) looks at the world and decides in which direction it wants
171167

172168
{{index "runRobot function"}}
173169

174-
Because we want robots to be able to remember things, so that they can make and execute plans, we also pass them their memory and allow them to return a new memory. Thus, the thing a robot returns is an object containing both the direction it wants to move in and a memory value that will be given back to it the next time it is called.
170+
Because we want robots to be able to remember things so they can make and execute plans, we also pass them their memory and allow them to return a new memory. Thus, the thing a robot returns is an object containing both the direction it wants to move in and a memory value that will be given back to it the next time it is called.
175171

176172
```{includeCode: true}
177173
function runRobot(state, robot, memory) {
@@ -188,7 +184,7 @@ function runRobot(state, robot, memory) {
188184
}
189185
```
190186

191-
Consider what a robot has to do to "solve" a given state. It must pick up all parcels by visiting every location that has a parcel and deliver them by visiting every location that a parcel is addressed to, but only after picking up the parcel.
187+
Consider what a robot has to do to "solve" a given state. It must pick up all parcels by visiting every location that has a parcel and deliver them by visiting every location to which a parcel is addressed, but only after picking up the parcel.
192188

193189
What is the dumbest strategy that could possibly work? The robot could just walk in a random direction every turn. That means, with great likelihood, it will eventually run into all parcels and then also at some point reach the place where they should be delivered.
194190

@@ -232,7 +228,7 @@ VillageState.random = function(parcelCount = 5) {
232228

233229
{{index "do loop"}}
234230

235-
We don't want any parcels that are sent from the same place that they are addressed to. For this reason, the `do` loop keeps picking new places when it gets one that's equal to the address.
231+
We don't want any parcels to be sent from the same place that they are addressed to. For this reason, the `do` loop keeps picking new places when it gets one that's equal to the address.
236232

237233
Let's start up a virtual world.
238234

@@ -304,11 +300,11 @@ Still, I wouldn't really call blindly following a fixed route intelligent behavi
304300

305301
To do that, it has to be able to deliberately move toward a given parcel or toward the location where a parcel has to be delivered. Doing that, even when the goal is more than one move away, will require some kind of route-finding function.
306302

307-
The problem of finding a route through a ((graph)) is a typical _((search problem))_. We can tell whether a given solution (a route) is a valid solution, but we can't directly compute the solution the way we could for 2 + 2. Instead, we have to keep creating potential solutions until we find one that works.
303+
The problem of finding a route through a ((graph)) is a typical _((search problem))_. We can tell whether a given solution (a route) is valid, but we can't directly compute the solution the way we could for 2 + 2. Instead, we have to keep creating potential solutions until we find one that works.
308304

309305
The number of possible routes through a graph is infinite. But when searching for a route from _A_ to _B_, we are interested only in the ones that start at _A_. We also don't care about routes that visit the same place twice—those are definitely not the most efficient route anywhere. So that cuts down on the number of routes that the route finder has to consider.
310306

311-
In fact, we are mostly interested in the _shortest_ route. So we want to make sure we look at short routes before we look at longer ones. A good approach would be to "grow" routes from the starting point, exploring every reachable place that hasn't been visited yet, until a route reaches the goal. That way, we'll only explore routes that are potentially interesting, and we know that the first route we find is the shortest route (or one of the shortest routes, if there are more than one).
307+
In fact, since we are mostly interested in the _shortest_ route, we want to make sure we look at short routes before we look at longer ones. A good approach would be to "grow" routes from the starting point, exploring every reachable place that hasn't been visited yet until a route reaches the goal. That way, we'll only explore routes that are potentially interesting, and we know that the first route we find is the shortest route (or one of the shortest routes, if there are more than one).
312308

313309
{{index "findRoute function"}}
314310

@@ -335,9 +331,9 @@ The exploring has to be done in the right order—the places that were reached f
335331

336332
Therefore, the function keeps a _((work list))_. This is an array of places that should be explored next, along with the route that got us there. It starts with just the start position and an empty route.
337333

338-
The search then operates by taking the next item in the list and exploring that, which means all roads going from that place are looked at. If one of them is the goal, a finished route can be returned. Otherwise, if we haven't looked at this place before, a new item is added to the list. If we have looked at it before, since we are looking at short routes first, we've found either a longer route to that place or one precisely as long as the existing one, and we don't need to explore it.
334+
The search then operates by taking the next item in the list and exploring that, which means it looks at all roads going from that place. If one of them is the goal, a finished route can be returned. Otherwise, if we haven't looked at this place before, a new item is added to the list. If we have looked at it before, since we are looking at short routes first, we've found either a longer route to that place or one precisely as long as the existing one, and we don't need to explore it.
339335

340-
You can visually imagine this as a web of known routes crawling out from the start location, growing evenly on all sides (but never tangling back into itself). As soon as the first thread reaches the goal location, that thread is traced back to the start, giving us our route.
336+
You can visualize this as a web of known routes crawling out from the start location, growing evenly on all sides (but never tangling back into itself). As soon as the first thread reaches the goal location, that thread is traced back to the start, giving us our route.
341337

342338
{{index "connected graph"}}
343339

@@ -372,7 +368,7 @@ runRobotAnimation(VillageState.random(),
372368

373369
if}}
374370

375-
This robot usually finishes the task of delivering 5 parcels in about 16 turns. That's slightly better than `routeRobot` but still definitely not optimal.
371+
This robot usually finishes the task of delivering 5 parcels in about 16 turns. That's slightly better than `routeRobot` but still definitely not optimal. We'll continue refining it in the exercises.
376372

377373
## Exercises
378374

@@ -382,7 +378,7 @@ This robot usually finishes the task of delivering 5 parcels in about 16 turns.
382378

383379
It's hard to objectively compare ((robot))s by just letting them solve a few scenarios. Maybe one robot just happened to get easier tasks or the kind of tasks that it is good at, whereas the other didn't.
384380

385-
Write a function `compareRobots` that takes two robots (and their starting memory). It should generate 100 tasks and let each of the robots solve each of these tasks. When done, it should output the average number of steps each robot took per task.
381+
Write a function `compareRobots` that takes two robots (and their starting memory). It generates 100 tasks and lets each of the robots solve each of these tasks. When done, it outputs the average number of steps each robot took per task.
386382

387383
For the sake of fairness, make sure you give each task to both robots, rather than generating different tasks per robot.
388384

@@ -441,11 +437,9 @@ hint}}
441437

442438
Most data structures provided in a standard JavaScript environment aren't very well suited for persistent use. Arrays have `slice` and `concat` methods, which allow us to easily create new arrays without damaging the old one. But `Set`, for example, has no methods for creating a new set with an item added or removed.
443439

444-
Write a new class `PGroup`, similar to the `Group` class from [Chapter ?](object#groups), which stores a set of values. Like `Group`, it has `add`, `delete`, and `has` methods.
445-
446-
Its `add` method, however, should return a _new_ `PGroup` instance with the given member added and leave the old one unchanged. Similarly, `delete` creates a new instance without a given member.
440+
Write a new class `PGroup`, similar to the `Group` class from [Chapter ?](object#groups), which stores a set of values. Like `Group`, it has `add`, `delete`, and `has` methods. Its `add` method, however, returns a _new_ `PGroup` instance with the given member added and leaves the old one unchanged. Similarly, `delete` creates a new instance without a given member.
447441

448-
The class should work for values of any type, not just strings. It does _not_ have to be efficient when used with large amounts of values.
442+
The class should work for values of any type, not just strings. It does _not_ have to be efficient when used with large numbers of values.
449443

450444
{{index [interface, object]}}
451445

0 commit comments

Comments
 (0)