Line Zipper is a quality challenge. One of my favorites. This is the sort of zipper we have in mind. If the input was six lines, like a/b/c/A/B/C, the output would be A/a/B/b/C/c.
M:1m+^M11@:ZZ
for 12.
There are actually two patterns in this file you can use. You can zip the lines based on their position, or join lines together based on their common prefix (the name of the country). The prefix pattern can be expressed in 13 strokes in a couple slightly different ways:
qqd*pjq11@qZZ
:%no<S-Tab>*ddNP^MZZ
Both methods use *
to find the matching line. The first one moves half the remaining file at once. It progresses like this (cursor in bold): a/b/c/A/B/C -> A/a/b/c/B/C -> A/a/B/b/c/C -> A/a/B/b/C/c. The second version runs on every line from 1 to 24, and for each line, moves its match above the line you started from. The progression step-to-step is the same, but you're moving one line across half the file, instead of half the file across one line. (Actually, every time it runs on an even-numbered line, *
takes the cursor back to the previous line, which got there in the last step, deletes it, and puts it right back. Whatever works.)
Anyway, that approach is a stroke too slow. Back on topic.
The winning approach ignores the contents of the lines, and uses their positions. This approach starts with the cursor in the middle, and moves a line from one end of the file to two lines away on the other side of the cursor. The cursor moves where the line was moved, so you can repeat with @:
. You can go in either direction:
M:1m+^M11@:ZZ
(the winning 12)*:$m--^M11@:ZZ
The first version starts at line 12/24 (M
), and repeatedly moves the current first line two lines beyond the cursor. The second version starts at line 13/24 (it's the same country, so it takes one stroke), and works in the opposite direction.
It may be surprising that +
and --
are symmetrical to each other. -
is the opposite of .
for an :m
target; they mean "before the current line" and "after the current line", respectively. --
means "before the previous line", which is opposite to +
, "after the next line".
If we use the winning pattern on the sample 6-line file, the macro progresses like this: a/b/c/A/B/C -> b/c/A/a/B/C -> c/A/a/B/b/C -> A/a/B/b/C/c.
Read the manual
:help :copy
for (very little) info on:t
and:m
, to copy and move lines around from the command line.:help 10.3
is a gentle explanation of command line ranges.:help cmdline-ranges
is the real explanation.:help @:
for repeating ex commands like macros. It runs the":
register like you'd expect, but it's as if there's an imaginary:
and^M
around it.:help linewise
might clarify the behavior ofd*
in the alternate solution.
Similar challenges
- Ugly spreadsheet copy/paste to CSV: Zips up data, but the act of joining lines as you go makes it play a lot different.
- Interweave two blocks of text: A simpler zip-and-join challenge, with tabs.
- Sort the cardinal numbers: Moving around a bunch of lines, but in a different way.
- Reverse and double space: Honestly it's totally different, but still, moving lines around.
- Sorting paragraphs: Maybe the most similar in this list, but you'll need to get tricky to figure out how.
No comments:
Post a Comment