650. Reversing Only the Letters
A line of text is given. Reverse the order of its LETTERS while leaving every other character exactly where it is.
ab-cd -> dc-ba
a-bC-dEf-ghIj -> j-Ih-gfE-dCba
Test1ng-Leet=code-Q! -> Qedo1ct-eeLg=ntse-T!
## The same skeleton as problem 618
618 reverses only the vowels; this reverses only the letters. Converge from both ends, skip whatever does not qualify, and swap when both pointers are sitting on something that does.
Only the test changes. That is worth noticing rather than treating as a new problem: the skeleton is "two pointers, a predicate, and a swap", and the predicate is a parameter.
## The sweep
i = 0, j = len-1
while i < j:
while i < j and s[i] is not a letter: i += 1
while i < j and s[j] is not a letter: j -= 1
if i < j:
swap s[i], s[j]
i += 1; j -= 1
## The two guards that matter
Both skip loops test i < j as well as the character. Without it, a line with no letters at
all runs a pointer off the end.
And the if i < j before the swap handles the case where the pointers MET, either on a single
middle letter or on a position holding no letter. --- and a are the tests for those two.
## Case travels with the letter
A letter keeps its own case as it moves, so ab-cd gives dc-ba and not DC-ba or anything
else. The characters are moved, not re-derived.
## Reading the input
The line may contain spaces and punctuation, so it must be read as a whole LINE. A whitespace-splitting reader sees separate tokens and solves a different problem while passing every single-word test.
## Cost
Time O(n). Space O(n) for the output, or O(1) if the buffer is edited in place.
Constraints - `1 ≤ length of the line ≤ 200000` - the line contains printable ASCII and no tab
Input
One line of text, at least one character long, made of printable ASCII.
Output
Print the line with only its letters reversed.
Hints
Four rungs, in order. The last two open once you have submitted an attempt. A wrong one counts.