Search code examples
vimsyntaxfizzbuzz

Vim syntax explanation of 'Remember FizzBuzz?' VimGolf challenge


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? 🧙‍♂️


Solution

  • 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.