Skip to content

Fun with Vimgolf 3: Swapping Words by Sorting

by mickey on January 14th, 2013

Jon over at Irreal’s been busy with VimGolf challenges, and I figured I’d throw in my two pieces of eight.

The “challenge” is a simple. Take this text:

And turn it into

As you can see, a simple transposition between two words on a line is all that we need, and Jon’s come up with a solution that solves it in 8 keystrokes. Arguably something like his solution is what I would do were I to do it in real life.

I’m not sure if the Vim guys count typing out strings of text as one atomic operation or if they count each character; in Emacs, arguably, each character is in itself a command as each key stroke will invoke self-insert-command but it’s more fun to think of strings of text as a single keystroke, for simplicity’s sake, and to give ourselves a sporting chance against our Vim nemeses.

So here’s my solution. It only solves this particular challenge and nothing more. It relies on the good ole sort order — that C come before S.

Command Description
C-x h Mark whole buffer
M-x sort-regexp-fields Run sort-regexp-fields. See Sorting Text by Line, Field and Regexp in Emacs for more information
Regexp specifying records to sort: \([a-z_]+\)$ We want each record -- that's the part of the line we want Emacs to use for sorting -- to be the last word on each line
Regexp specifying key within record: \1 The key -- that's the part inside the capturing group from above -- we want to sort by is the entire capturing group.

And we're done. So how does it work? Well, we rely on the side effect that the word CHALLENGE_FOLDER is less than, lexicographically, SOLUTIONS_FOLDER, because C comes before S.

It boils down to this: sort-regexp-fields is pure magic. As my article on the subject talks about at length, you can tell Emacs to only sort by parts of a line -- the part that matches the regular expression -- and using that match, you can then tell Emacs how you want to sort that data. We tell Emacs to sort by the last word on each line and leave the rest untouched. Simple :)

So how many keystrokes is that? Good question. I don't know: it depends on how you count it. Two if you count the commands only; four if you count the commands and the prompts; and many more if you count each character.

As always, these challenges are pointless (though fun!) but they do force you to think on your feet.

From → All Articles

9 Comments
  1. Hrm, without magic it’s doable with 8 keystrokes in Emacs, too, given that we have to start at the beginning of the buffer:

    1. C-s
    2. =
    3. C-k
    4. Down
    5. C-y
    6. C-k
    7. Up
    8. C-y

    .oO( C-x C-s ;-)

    That’s 8 if you don’t count pressing the Control key extra.

    If you count the Control key extra, you’ll probably use C-n and C-p instead of Up and Down and keep the Control key pressed as long as possible. You’ll just have to lift it for the “=”.

    If you use M-d instead of C-k you’ll need also one C-u C-y instead of one C-y, so that would be 9 key strokes.

    I also tried to solve it with Rectangles (C-x r …), but there seems no possibility to narrow-to-rectangle. That’d have been neat: Mark a rectangle around the two words to exchange, narrow-to-rectangle, transpose-words (or transpose-lines), done. :-)

  2. Ah, didn’t notice that this is considered the “default” solution and posted over in the referred blog posting. :-)

    • mickey permalink

      Hey, no problem; your solution (or something along those lines) is what I would do were I to solve it ‘in real life.’

      I do have another fun solution to this one that does it in a single replace-regexp… but that’s part of a bigger, upcoming article ;)

  3. Joe Riel permalink

    Depending on the mode, you might be able to use \s_+$
    to match the field and \& to select the key.

  4. Kevin Brubeck Unhammmer permalink

    If you have CUA-mode on, you can do it in 6 steps:

    C-s
    =
    C-RET
    C-n
    C-e
    M-R

    (that’s meta-shift-r for the last one)

    • Kevin Brubeck Unhammmer permalink

      or “cua-selection-mode”, in case you only want the wonderful rect stuff from cua and not the whole C-v/C-c stuff

    • Kevin Brubeck Unhammmer permalink

      note that this is 6 keypresses (if chords are one keypress)

Trackbacks & Pingbacks

  1. Sorting Rectangles | Irreal
  2. Evaluating Lisp Forms in Regular Expressions | Mastering Emacs

Leave a Reply

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

Subscribe to this comment feed via RSS