Learn Practice Daily golf Reference
The Vim Way·Lesson 2 of 7·8 min·0/8 exercises

One key to move, one to repeat

The dot formula: make one change you can stamp, then slide and stamp: ; . along a line, j . down a run. s swaps one character.

Scene

11:25 a.m. Ten happy-hour lines left, and they're scattered: two lines apart here, three commas along a line there. The stamp still works. Getting to each spot is what's slow.

The lunch rush starts at noon, and the packing table downstairs is already busy. Watch how they do it.

From memory

Warm-up from earlier chapters

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

Delete the character under the cursor, then do the same one line down.
press the keys…3 keys
1 of 2
Delete the character under the cursor, then do the same one line down.

Slide, stamp

On the packing table the bags sit in a row: slide your hand to the next bag, stamp it, slide, stamp. That's the dot formula. Make one change you can stamp, then every repeat costs two keys: one to move to the next spot, and . to stamp it.

Before
const total = base+tax+tip;
f+s + Esc
const total = base + tax+tip;
;.
const total = base + tax + tip;
One change on the first +, then ; slides to the next + and . stamps it.

s swaps one character

On its last night, the Formatter squeezed the spaces out of the maths. s deletes the character under the cursor and starts Insert mode, so on a squeezed + you press s, type + , and Esc: one change, ready to stamp. f+ gets you to the first one, and ; slides to each one after.

1const url = base+"/api/"+version+"/users";
NORMALLoading the editor…1:1
Try it

Give the operators room

Three lines, two squeezed operators each. f+ (or f*) to the first, s to fix it, then ; . for the second.

1 of 3Fix the marked spots · 2 left
1export function receipt(order: Order) {
1 const total = order.base+order.tax+order.tip;
2 const url = API+"/receipts/"+order.id;
3 const ms = order.minutes*60*1000;
4 return { total, url, ms };
5}
NORMALLoading the editor…1/30.0s1:1

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

Check yourself

Stamp without sliding

1sum(a,b,c)
NORMAL
Keys pressed: f,a␣Esc..

You press f,, then a, a space and Esc. Then . twice, with no ;. What does the line look like?

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

Let the list breathe

Every comma lost the space after it. Fix the first with f, and a, then slide and stamp along the line.

Fix the marked spots · 4 left
1export const HAPPY_HOUR = ["al-pastor","veggie","carnitas","birria","churros"];
NORMALLoading the editor…0.0s1:1

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

Pick the slide

The stamp stays the same; the slide depends on where the next bag is. Directly below? j .. The next copy of a character on the same line? ; .. Look for the move that lands exactly on the next spot: one key to slide, one to stamp. A longer slide still gets the job done; it just costs more keys.

f+
const total = base+tax+tip+fee+rush;
5 keys
f+ slides to the first +, and each ; to the next: one key per bag.
Try it

One slide too far

You stamped the first comma, then pressed ; twice and slid right past the second. , slides back the other way, as it did in track 1. Stamp the one you missed, then carry on along the line.

One comma too far. Slide back, stamp it, then stamp the rest.
1export const SIDES = ["chips", "guac","salsa","churros"];
NORMALLoading the editor…0.0s1:46

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

From memory

Slide and stamp, from memory

Read the situation, press the keys.

Slide to the next copy of the character you last found.
scroll here, then press the keys
1 of 4
Slide to the next copy of the character you last found.
Challenge

Happy-hour spacing

Squeezed operators and lost semicolons across the pricing code. Make the first fix, then pick the slide that reaches the next spot.

Stuck? Show a hintoperators: f+s + <Esc> then ;. · semicolons: A;<Esc> then j.
1 of 8Change the red text to ·*·
1export function happyHour(item: Item, hour: number) {
1 const base = item.price*item.qty;
2 const off = hour >= 17 && hour < 19 ? base * 0.2 : 0;
3 const tax = (base - off) * TAX_RATE;
4 const total = base - off+tax+item.tip;
5 log("happy hour", item.id, base, off, total);
6 return Math.round(total * 100) / 100;
7}
8
9export const LIMITS = { maxQty: 12, maxTip: 20, rushMinutes: 45 };
NORMALLoading the editor…1/80.0s1:1

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

Boss round

The tax line

The happy-hour function itself. Semicolons down the top three lines, room around every + in the total, and a space after every comma in the log call. Three changes, each stamped along its own slide.

Stuck? Show a hintA;<Esc> then j. j. · f+s + <Esc> then ;. · f,a <Esc> then ;. ;. ;.
1 of 3Fix the marked spots · 3 left
1export function happyHour(item: Item, hour: number) {
1 const base = item.price * item.qty;
2 const off = hour >= 17 && hour < 19 ? base * 0.2 : 0;
3 const tax = (base - off) * TAX_RATE;
4 const total = base - off+tax+item.tip;
5 log("happy hour",item.id,base,off,total);
6 return Math.round(total * 100) / 100;
7}
NORMALLoading the editor…1/30.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

The packing line

Endless spacing and semicolon repairs, bigger batches as you go. Find the rhythm and keep it.

Level 1Change the red text to ·+·
1function averageRating(reviews: Review[]) {
1 if (reviews.length === 0) return 0;
2 const sum = reviews.reduce((acc, r) => acc+r.stars, 0);
3 const avg = sum / reviews.length;
4 return Math.round(avg*10) / 10;
5}
6
7const best = reviews.filter((r) => r.stars === 5);
8console.log("five-star reviews:", best.length);
NORMALLoading the editor…lv 1 · 0 done0.0s1:1

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