Skip to content

Fun with Vimgolf 2: Sum your vimgolf rank

by mickey on November 3rd, 2011

Overall Vimgolf Rank

Link to challenge.

Suppose you are trying to figure out what your overall rank is at Vimgolf(the sum of all the ranks you got), and as a Vim ninja you decided to use Vim to do the job. Your solution should work for every Vimgolf profile page(The actual input file for this challenge is my Vimgolf profile page). So, direct answer insertion is considered cheating.

Here’s another fun vimgolf challenge. The task is simple: get the sum of all the ranks on your vimgolf profile page.

A pretty specific goal, but the concept will work with anything involving summing numbers in a buffer. Anyway, off we go..

Given this input:

Get this output:

Now, in the vim challenge you are supposed to end up, as I understand it, with a buffer with nothing but the result — but that’s not a very productive (nor easy) way to accomplish the task.

Option 1: Using Registers

The first thing we need to do is mark the entire buffer with C-x h. Next, we need to set an emacs register — which is a simple store and recall register that you can save things like text, numbers, the point and frame or window configurations to for later re-use — by typing M-0 C-x r n a. To break that down a bit, we use the universal argument M-0 to tell Emacs that we want the number zero stored in a numeric register a by calling number-to-register, bound to C-x r n.

Next, we will use query-replace-regexp bound to C-M-% and use a little-known feature of Emacs’s regexp engine to, in effect, use the side effect of a regexp replace on each match.

Input the following:

So here we are invoking increment-register (bound to C-x r +) and passing it the contents of the regexp capture group 1 (the rank) by first converting it to an integer so increment-register can make sense of it. We are also passing ?a as we need to give it the character a and not the string.

When you replace all matches (type !) you’ll see that Emacs will do a “rolling sum” by returning the contents of the new register and thus slowly add up all the ranks, one by one. Thus, if you scroll to the very bottom the last “match” will have the correct answer.

Obviously altering the text is probably not desirable so simply C-/ to undo the regexp replace.

And that’s it. Not the snappiest solution but it shows what you can do with Emacs if you really want to.

Option 2: Using Elisp

Well, if you can write elisp this problem is trivial; the code below will do the same as the above, but it’s a little bit neater and perhaps a bit easier to recycle for other tasks as well.

If you want to know how to run it, then you should read my article on Evaluating Elisp in Emacs.

2 Comments
  1. You can shorten your keystroke count by getting rid of the string-to-number in the replacement string for query-replace-regexp like this:

    \,(increment-register \#1 ?a)

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS