Learn Practice Daily golf Reference
Foundations·Lesson 5 of 6·11 min·0/13 exercises

Leap within a line

0 ^ $ jump to the line ends; f and t jump straight to any character, and ; repeats.

Scene

12:03 p.m., day two. The lunch rush is on, and one rider has now circled the same block five times. Somewhere in delivery.ts an address is off by a single character, buried in a line longer than your screen.

Word hops would get you there eventually. But you can see the character you want. Why not ride straight to it?

From memory

Warm-up from earlier chapters

Two from earlier chapters, from memory, before the new idea. Two wrong tries show the answer.

Right after the cursor.
press the keys…
1 of 2
Right after the cursor.

The corner, the first house, the end of the street

Think of a line as a street with a house on every character. 0 takes you to the corner where the street begins, column zero. ^ skips the empty lots of indentation and stops at the first house: the first character that isn't a space. $ rides to the end of the street. In indented code, ^ is usually the one you want.

const fee = distanceKm > 5 ? 2.5 : 0;0^$
One press each from the cursor: 0 to the corner, ^ to the first house, $ to the end of the street.
1 const fee = distanceKm > 5 ? 2.5 : 0;
NORMALLoading the editor…1:25
Try it

Both ends

Some targets sit at the start or end of a line. 0, ^ and $ get there in one key.

1 of 5Move the cursor onto the
1 enqueue(order: Order) {
1 this.queue.push(order);
2 this.startNext();
3 }
4
5 startNext() {
6 if (this.busy || this.queue.length === 0) return;
7 this.busy = true;
8 const next = this.queue.shift();
9 cook(next).then(() => this.finish());
10 }
NORMALLoading the editor…1/50.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

f rides to the house you can see

f plus a character rides you straight to the next house with that sign on it. f, rides to the next comma; f( to the next bracket. Look at where you want to be, name the character, and you're at its door.

f,
assign(order, nearest, { rush: true }, eta, "bike");
8 keys
Every comma is a house f, can ride to. Each arc is one ride.
1assign(order, nearest, { rush: true }, eta, "bike");
NORMALLoading the editor…1:1
Try it

Ride to it

Each target sits on a character you can name. Ride there with f.

1 of 5Move the cursor onto the
1const MAX_DISTANCE_KM = 8;
1const riders = await loadRiders({ online: true });
2const nearest = riders.sort((a, b) => a.distance - b.distance)[0];
3if (!nearest || nearest.distance > MAX_DISTANCE_KM) {
4 return refund(order, "No rider nearby, sorry!");
5}
6assign(order, nearest);
7log("assigned", order.id, nearest.name);
NORMALLoading the editor…1/50.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Check yourself

Not on this street

1const eta = route(start, end);
1return eta.minutes;
NORMAL
Keys pressed: fm

You press fm. The only m is on the next line, in minutes. Where does the cursor go?

Pick an answer (or press its number), then watch the engine prove it.
Try it

The circling rider

Here's the rider's stop, straight from delivery.ts: the street number has a digit too many, and the note is missing a letter. Ride to each one with f, then fix it with x or i.

1 of 2Delete the text marked red
1 { street: "Calle Ocho 14420", lat: 25.7656, lng: -80.2190, note: "blue dor" },
NORMALLoading the editor…1/20.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Route updatedFinish the exercise above to see it.

t pulls up one house short

t is f's careful twin: it rides till the character and pulls up one house before it. That's exactly where you want to be when you're about to type in front of a bracket, or delete up to it.

f)
log(fmt(order.id), eta(nearest));
4 keys
t)
log(fmt(order.id), eta(nearest));
4 keys
Same brackets, two ways to stop: f) at the bracket, t) one house before it.
1log(fmt(order.id), eta(nearest));
NORMALLoading the editor…1:1
Try it

Just before

These targets sit right before a bracket, quote or comma. t pulls up there in two keys.

1 of 5Move the cursor onto the
1const MAX_DISTANCE_KM = 8;
1const riders = await loadRiders({ online: true });
2const nearest = riders.sort((a, b) => a.distance - b.distance)[0];
3if (!nearest || nearest.distance > MAX_DISTANCE_KM) {
4 return refund(order, "No rider nearby, sorry!");
5}
6assign(order, nearest);
7log("assigned", order.id, nearest.name);
NORMALLoading the editor…1/50.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

The next house, or back again

Missed? Don't name the character again. ; rides on to the next house with the same sign, and , rides back the way you came. Four commas along is f, then ; ; ;: five keys, no counting, and you see each stop as you pass it.

f,;
notify(user.phone, order.id, rider.name, eta, "on its way");
0 keys
w
notify(user.phone, order.id, rider.name, eta, "on its way");
0 keys
Riding comma to comma against hopping word by word, racing to the last comma.
1notify(user.phone, order.id, rider.name, eta, "on its way");
NORMALLoading the editor…1:1
Try it

Ride on

Each target is a few commas or brackets along. Ride once, then ; until you arrive; , if you overshoot.

1 of 5Move the cursor onto the
1const MAX_DISTANCE_KM = 8;
1const riders = await loadRiders({ online: true });
2const nearest = riders.sort((a, b) => a.distance - b.distance)[0];
3if (!nearest || nearest.distance > MAX_DISTANCE_KM) {
4 return refund(order, "No rider nearby, sorry!");
5}
6assign(order, nearest);
7log("assigned", order.id, nearest.name);
NORMALLoading the editor…1/50.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Try it

Overshot

Each ride starts one or two stops too far. Don't name the character again: , rides back the way you came.

1 of 3One ; too many: you rode past the comma after rider.name. Back one with ,.
1notify(user.phone, order.id, rider.name, eta, "on its way");
NORMALLoading the editor…1/30.0s1:45

This exercise needs a keyboard. Read on, and play it at your computer.

Check yourself

Till, then again

1const eta = route(start, end, { avoid: "hills" });
NORMAL
Keys pressed: t,;

You press t,, then ;. Where does the cursor end up?

Pick an answer (or press its number), then watch the engine prove it.

Capitals ride backwards

F and T turn around and ride back toward the corner: F( stops at the previous bracket, T( pulls up just after it. And ; keeps riding in whichever direction you set off.

1assign(order, nearest, { rush: true }, eta, "bike");
NORMALLoading the editor…1:52
Try it

Both directions

Targets on both sides of the cursor now. Pick your direction before you ride.

1 of 6Move the cursor onto the
7const MAX_DISTANCE_KM = 8;
6const riders = await loadRiders({ online: true });
5const nearest = riders.sort((a, b) => a.distance - b.distance)[0];
4if (!nearest || nearest.distance > MAX_DISTANCE_KM) {
3 return refund(order, "No rider nearby, sorry!");
2}
1assign(order, nearest);
8log("assigned", order.id, nearest.name);
NORMALLoading the editor…1/60.0s8:40

This exercise needs a keyboard. Read on, and play it at your computer.

if (!nearest || nearest.distance > MAX_DISTANCE_KM) {0^F(f>t)$
The whole kit, one press each from the same cursor. Capitals ride backwards and are drawn below the line.
From memory

Name the jump

No scrolling up. Read the situation, press the keys.

To the end of the line.
scroll here, then press the keys
1 of 6
To the end of the line.
Challenge

Address patrol

Dispatch wants every assignment in delivery.ts double-checked before the next wave of orders. Twelve stops, jumps getting longer. Rides, repeats, line ends: whatever gets you there in the fewest keys.

1 of 12Move the cursor onto the
1const MAX_DISTANCE_KM = 8;
1const riders = await loadRiders({ online: true });
2const nearest = riders.sort((a, b) => a.distance - b.distance)[0];
3if (!nearest || nearest.distance > MAX_DISTANCE_KM) {
4 return refund(order, "No rider nearby, sorry!");
5}
6assign(order, nearest);
7log("assigned", order.id, nearest.name);
NORMALLoading the editor…1/120.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Boss round

The next wave

The second wave of lunch orders goes out at one, and dispatch wants the whole stops list right before it does. Four more addresses have a character too many or too few. Ride to each one, fix it, and nobody else circles a block today.

Stuck? Show a hintf or t to the spot (; to ride on, , if you overshoot), then x for an extra character, i + the missing one + <Esc>
1 of 4Type 6 where it's shown in green
1export const STOPS = [
1 { street: "Calle Ocho 1420", lat: 25.7656, lng: -80.2190, note: "blue door" },
2 { street: "Brickell Ave 801", lat: 25.763, lng: -80.1917, note: "ring twice" },
3 { street: "Coral Way 2601", lat: 25.7505, lng: -80.24409, note: "side " },
4 { street: "Flagler St 9", lat: 25.7743, lng: -80.1937, note: "lobby" },
5];
NORMALLoading the editor…1/40.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.

Extra practice optional

The chapter is done. These rounds keep going as long as you like: stop whenever it stops being useful.

Endless

Dispatch never sleeps

Endless targets on fresh code, longer rides every level. Every find and repeat is allowed.

Level 1Move the cursor onto the
1// delivery zones: where riders go, and what it costs to get there
1export const ZONES = [
2 { name: "Little Havana", lat: 25.7656, lng: -80.219, fee: 2.5 },
3 { name: "Brickell", lat: 25.7663, lng: -80.1917, fee: 2 },
4 { name: "Wynwood", lat: 25.8005, lng: -80.1994, fee: 3 },
5 { name: "Coral Way", lat: 25.7505, lng: -80.2409, fee: 3.5 },
6 { name: "Downtown", lat: 25.7743, lng: -80.1937, fee: 1.5 },
7 { name: "Edgewater", lat: 25.8001, lng: -80.1887, fee: 3 },
8];
9
10export function zoneFor(lat: number, lng: number) {
11 return ZONES.find((z) => Math.abs(z.lat - lat) < 0.01 && Math.abs(z.lng - lng) < 0.01);
12}
NORMALLoading the editor…lv 1 · 0 done0.0s1:1

This exercise needs a keyboard. Read on, and play it at your computer.