Vim syntax explanation of 'Remember FizzBuzz?' VimGolf challenge

138 Views Asked by At

I worked my way up (or down, if you want) to the best score of Remember FizzBuzz? at VimGolf, but I have a hard time interpreting the solution:

33o<CR> Fizz<CR><C-H><Esc><C-V>A4k<C-H>.@.<C-U>Buzz<Esc>@.<C-V>GI0<Esc>gvg<C-A>ZZ

I understand

the beginning part of adding lines with "Fizz" – 33o<CR> Fizz<CR><C-H><Esc> – and the end where the preceding line numbers are added – <C-V>GI0<Esc>gvg<C-A>ZZ

but I don't understand

the middle part where the "Buzz" lines are added, i.e. <C-V>A4k<C-H>.@.<C-U>Buzz<Esc>@.. 4k<C-H> moves the cursor to the correct place and the last @. executes the content of the . register, but that's as much as I can fathom.

Can someone explain the Vim magic used here? ‍♂️

1

There are 1 best solutions below

6
romainl On BEST ANSWER

The first part:

33o<CR> Fizz<CR><C-H><Esc>

puts Fizz on every line that is a multiple of 3, solving the first requirement of FizzBuzz. It's done with 33 iterations of:

  1. jump over an empty line,
  2. put Fizz on next line,
  3. open an empty line,
  4. leave insert mode.

33 blocks of 3 lines are added after line 1 so you get 100 lines in total and the cursor is left on line 100.

See :help o.

The second part:

<C-V>A4k<C-H>.@.<C-U>Buzz<Esc>

essentially creates a recursive macro that appends Buzz to lines that are a multiple of 5, instrumental in solving the second and third requirements of FizzBuzz.

In detail:

  1. <C-v>A to start insertion on column 2, aligned with the Fizzs from part 1,
  2. insert 4k,
  3. do <C-h> to delete the k,
  4. insert .@.,
  5. do <C-u> to delete everything that was inserted on the current line,
  6. insert Buzz,
  7. leave insert mode with <Esc>.

That is a lot of work just to insert Buzz on one line but this part actually serves three purposes:

  1. append Buzz to the current line (that is incidentally the last multiple of 5),
  2. record that as one edit, repeatable with .,
  3. record all that as a recursive macro in register ..

The macro in register . is:

  1. 4k, move up 4 lines,
  2. <C-h>, move the cursor back one character,
  3. . repeat last edit, so append Buzz to curent line (if there's Fizz, get FizzBuzz, if not, get Buzz),
  4. @. play back macro in register ..

See :help v_b_A, :help i_ctrl-u, :help ., help "., :help @.

The third part:

@.

plays back the recursive macro described above so it goes up 4 lines, then up 4 lines, and so on, solving the second and third requirements of FizzBuzz.

The fourth part:

<C-V>GI0<Esc>

inserts a 0 at the beginning of each line.

See :help v_b_I.

The fifth part:

gvg<C-A>

reselects the last visual block and then increments each 0 sequentially.

See :help gv and :help v_g_ctrl-a.

The sixth part:

ZZ

writes the file and quits Vim.

See :help ZZ.