Fun with Vimgolf 4: Transpositioning text with Tables
Here’s another vim challenge, and one you might actually encounter frequently in real life.
Transpose the original lines in separate columns, one for each line.
Simple, really; a transposition here, some alignment there… but can we do better than the good ole’ brute force approach the Vim guys will invariably use? Can we do it without a call to a shell commands like column and paste? (Psst.. yes we can! It’s Emacs!)
Here’s the original data:
ultricies, vehicula, felis, sed, auctor, aenean, euismod, semper, quam, dapibus nibh, consequat, consequat, maecenas, sit, amet, mauris, justo, quis, porttitor curabitur, pharetra, euismod, orci, sit, amet, ullamcorper, mi, tincidunt, et vitae, lorem, at, mi, feugiat, convallis, ac, eget, dui, fusce blandit, iaculis, nulla, sit, amet, dolor, nec, est, ornare, volutpat
… Standard comma-, and newline-delimited data, and we must turn it into this:
ultricies nibh curabitur vitae blandit vehicula consequat pharetra lorem iaculis felis consequat euismod at nulla sed maecenas orci mi sit auctor sit sit feugiat amet aenean amet amet convallis dolor euismod mauris ullamcorper ac nec semper justo mi eget est quam quis tincidunt dui ornare dapibus porttitor et fusce volutpat
Looking into the challenge, I was already thinking “tables” — Emacs tables. Transposition is a common operation in tables (spreadsheets) and mathematics, and Emacs can do both very well indeed.
So here’s what I did, utilizing our old friend org-mode; or rather, one of its subsidiary libraries. You don’t have to be in org-mode for this trick to work. It echoes an earlier VimGolf challenge I did where I used its hierarchical “sort” function to sort an address book: Fun with Vimgolf 1: Alphabetize the Directory.
| Command | Description |
|---|---|
C-x h |
Mark the whole buffer |
M-x org-table-convert-region |
Converts a region into an org table. The defaults use comma and new line separators by default. Bonus. |
M-x org-table-transpose-table-at-point |
As the name implies this will transpose our table as required by the Vimgolf challenge. |
C-x C-x |
Exchange point and mark. |
M-x replace-regexp |
Replace: ^| \||With: RET
Replace the pipe at the beginning of the line and a whitespace, or any pipe. |
M-x delete-trailing-whitespace |
Delete trailing whitespace. Could also be done with a more sophisticated regexp in the penultimate step. |
Done right, and it should look like this:
ultricies nibh curabitur vitae blandit vehicula consequat pharetra lorem iaculis felis consequat euismod at nulla sed maecenas orci mi sit auctor sit sit feugiat amet aenean amet amet convallis dolor euismod mauris ullamcorper ac nec semper justo mi eget est quam quis tincidunt dui ornare dapibus porttitor et fusce volutpat
Six “keystrokes” (for an arbitrarily large definition of “keystroke”…), but done the Emacs way. The best score on VimGolf is currently 31 (characters). Very impressive, but would it work on a 20×20 or with variable-length rows? “Think Abstract,” the developer cried.
The result above should be identical to that of the Vimgolf output, but done without the hyper-specialized and brittle solutions (most?) of the VimGolfers employ.
I didn’t tweak the cell width (whitespacing between each word) for each column; that it aligns perfectly with VimGolf’s output is dumb luck. Maybe they generated the resultant output in Emacs?
Nevertheless, the solution is “typical Emacs” and would scale well to very large datasets, and you don’t have to worry about things like unusually long cells; uneven number of rows and columns; etc.
Mastering Emacs
Trackbacks & Pingbacks