[Question]
  [
## Goal
This is a simple challenge. Your goal is to unscramble a string by swapping each letter with the next letter of the same case, while leaving non-letter characters unchanged.
[![example](https://i.stack.imgur.com/ubgD2.png)](https://i.stack.imgur.com/ubgD2.png)
## Step by step explanation
1. The first character is a `E`. We look for the next letter in upper case: it's a `C`. We swap these characters, which leads to `CdoE!`.
2. We advance to the next character: this is a `d`. We look for the next letter in lower case: it's a `o`. We swap these characters, which leads to `CodE!`.
3. We advance to the next character: this is the `d` that we've just moved here. We ignore it, because it has already been processed.
4. We advance to the next character: this is the `E` that was moved here at step #1. We ignore it, because it has already been processed.
5. We advance to the next character: this is a `!`. We ignore it, because it's not a letter.
## Rules
* You can assume that the input string is made exclusively of printable ASCII characters, in the range 32 - 126.
* You may write either a full program or a function, which either prints or returns the result.
* If the input string contains an odd number of letters, the last remaining letter can't be swapped with another one and should remain in place, no matter its case. The same logic applies if the string contains an even number of letters, but an odd number of uppercase letters and an odd number of lowercase letters.
* This is code-golf, so the shortest answer in bytes wins. Standard loopholes are forbidden.
## Test cases
```
Input : lLEhW OroLd!
Output: hELlO WorLd!
Input : rpGOZmaimgn uplRzse naC DEoO LdGf
Output: prOGRamming puzZles anD COdE GoLf
Input : eIt uqHKC RBWOO xNf ujPMO SzRE HTL EOvd yAg
Output: tHe quICK BROWN fOx juMPS OvER THE LAzy dOg
Input : NraWgCi: Nsas-eNEiTIsev rNsiTG!!
Output: WarNiNg: Case-sENsITive sTriNG!!
```
Not-so-random test cases:
```
Input : (^_^)
Output: (^_^)
Input : AWCTY HUOS RETP
Output: WATCH YOUR STEP
Input : hwn oeesd acsp nawyya
Output: who needs caps anyway
Input : SpMycaeIesKyBorekn
Output: MySpaceKeyIsBroken
Input : D's mroyr, Ivam. I'e faardi I act'n od htta.
Output: I'm sorry, Dave. I'm afraid I can't do that.
```
  
[Answer]
# [Retina](https://github.com/m-ender/retina), 53 bytes
Not really clever, but a clean and quite readable solution
```
([a-z])(.*?)([a-z])
$3$2$1
([A-Z])(.*?)([A-Z])
$3$2$1
```
[Try it online!](https://tio.run/nexus/retina#@68RnahbFaupoadlrwllc6kYqxipGHJpRDvqRsGlwGyo1P//fkWJ4enOmVYKfsWJxbqpfq6ZIZ7FqWUKRX7FmSHuiooA "Retina – TIO Nexus")
[Answer]
# [MATL](https://github.com/lmendo/MATL), 22 bytes
```
2:"tttk<f2etAZ))P5M(Yo
```
[Try it online!](https://tio.run/nexus/matl#@29kpVRSUpJtk2aUWuIYpakZYOqrEZn//796qmeJQmmhh7ezQpBTuL@/QoVfmkJpVoCvv0JwVZCrgkeIj4Krf1mKQqVjujoA) Or [verify all test cases](https://tio.run/nexus/matl#DcpNC4IwGADge7/itcvq0EXoIl1Mh0pzExtIQtDAaZZfbVPKP28@5@ex2M7WGPM@lbY0br7fJ8d4d@uXu88X1BD8zICpnhQW2iA1BCxvRd1WHYxDk85aQic88HHPgBRBuR4ZGRg/4cWD9JwxBl9awvhKYgbXOcUQcgKYTQX83GrdVIms8moHqBb6ICmueaTlBIrqmgeWhf4).
### How it works
```
2:"       % Do the following twice
  ttt     %   Input string (implicit). Push three more copies
  k       %   Convert to lowercase
  <f      %   Indices of characters that had their code point increased by
          %   the lowercase conversion, i.e. that were uppercase letters
  2e      %   Convert to 2-row matrix. This pads a zero in the lower-right 
          %   corner if necessary
  tAZ)    %   Keep only columns that don't contain zeros. Thus if there
          %   was a character that can't be swapped it will be ignored             
  )       %   Get 2-row matrix of characters at those positions
  P       %   Flip vertically. This does the swapping
  5M      %   Push matrix of original indices again
  (       %   Write the swapped characters onto their original positions
  Yo      %   Change case. In the first iteration, this prepares the
          %   string so the second iteration will process the letters that
          %   were originally lowercase. In the second iteration, it
          %   undoes the change of case 
          % End (implicit)
          % Display (implicit)
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~21~~ ~~20~~ ~~19~~ 18 bytes
```
s2UF,
nŒlTÇyJịŒsµ⁺
```
[Try it online!](https://tio.run/nexus/jelly#BcE9DoIwGADQvaf42HVxdFOsgGJrEEN0I6Eghj9bIcKmC4Mb53DURTYJB4GL4HuDmOyXIxS1VWA2Zb7q6mdbid@nv3@Hrn43Zf94HYYh0PHJAspj3ZEQTxR6DG0/9CJIk8AoBIPIlmGBYwq6o7iIaVdIL@paBmNuUQo34kJ63m4o7AoDg2rqgGnmQD7zEOG25cn@FIiwxZgR7JuaYBlwInxTkaQ/ "Jelly – TIO Nexus")
### How it works
```
nŒlTÇyJịŒsµ⁺  Main link. Argument: s (string)
 Œl           Convert to lowercase.
n             Test for inequality.
   T          Truth; yield all indices of 1's.
    Ç         Call the helper link. Yields [A, B] (pair of lists).
      J       Indices; yield I := [1, ..., len(s)].
     y        Translate; replace the integers of I that occur in A with the
              corresponding integers in B.
        Œs    Swapcase; yield s with swapped case.
       ị      Use the translated index list to index into s with swapped case.
          µ   Combine all links to the left into a chain.
           ⁺   Duplicate the chain, executing it twice.
s2UF,         Helper link. Argument: J (list of indices)
s2            Split J into pairs. If the length is odd, the last list will be
              a singleton list.
  U           Upend; reverse each pair. This is a no-op for singletons lists.
   F          Flatten, concatenating the pairs.
    ,          Pair the previous result with J.
```
[Answer]
# Bash + Unix utilities, ~~77~~ ~~62~~ ~~57~~ ~~56~~ 54 bytes
```
sed -r "s/([$1)([^$1*)([$1)/\3\2\1/g"||$0 a-z]|$0 A-Z]
```
Input in stdin.
Output in stdout.
(In this last version, stderr happens to be written to also, but PPCG consensus seems to be that that's OK -- [stderr is simply ignored.](http://meta.codegolf.stackexchange.com/questions/4780/should-submissions-be-allowed-to-exit-with-an-error/4781#4781))
Edit 1: Thanks to @Dennis for 15 bytes! Improvements: (a) Taking input via stdin; (b) combining 2 sed scripts into one; and (c) replacing tr with substitution via bash parameter expansion; (b) and (c) disappeared in Edit 2.
Edit 2: Shorter by 5 additional bytes. Used a function call to replace both (b) and (c) in Edit 1. 
Edit 3: One more byte -- passed ] as part of the function arguments.
Edit 4: Replaced the two function calls with calls to the program itself when it has no arguments.
Testbed and sample output:
```
for x in 'lLEhW OroLd!' 'rpGOZmaimgn uplRzse naC DEoO LdGf' 'eIt uqHKC RBWOO xNf ujPMO SzRE HTL EOvd yAg' 'NraWgCi: Nsas-eNEiTIsev rNsiTG!!' '(^_^)' 'AWCTY HUOS RETP' 'hwn oeesd acsp nawyya' 'SpMycaeIesKyBorekn' "D's mroyr, Ivam. I'e faardi I act'n od htta."; do ./swapping <<<"$x" 2>/dev/null; done
hELlO WorLd!
prOGRamming puzZles anD COdE GoLf
tHe quICK BROWN fOx juMPS OvER THE LAzy dOg
WarNiNg: Case-sENsITive sTriNG!!
(^_^)
WATCH YOUR STEP
who needs caps anyway
MySpaceKeyIsBroken
I'm sorry, Dave. I'm afraid I can't do that.
```
[Answer]
## ES6, ~~185~~ 95 bytes
```
i=>(o=[...i]).map((c,j)=>/[a-z]/i.test(c)?o[e=c>"Z"]=1/(b=o[e])?o[o[j]=o[b],b]=c:j:0)&&o.join``
```
Solution severely shortened with the help of @Neil, @Arnauld and @edc65
Explanation
```
f = i =>
  // Get array of characters from input string
  (o = [...i])
    .map((c, j) => 
      // Check if it's a text character, otherwise skip it
      /[a-z]/i.test(c) ? 
        // Get last character position for case
        // merged with setting a variable for if the character is lowercase
        // merged with storing the current case character position,  
        // under properties on the array (with keys "true" or "false")
        o[e = c>"Z"] =
          // Check if there exists a character position to switch with
          // merged with storing the current position for quick access
          1/(b=o[e]) ? 
            // This statement will end up returning the Array subset, 
            // which will be falsy in the above conditional since (1/[])==false
            o[
              // Switch left character to the right
              o[j]=o[b]
            // Switch right character to the left
            ,b]=c : 
            // No character exists for case, so return current character position
            j
         // It was not a text character, so do nothing
         :0
      )
  // Join array and return as result
  && o.join``;
`lLEhW OroLd!
NraWgCi: Nsas-eNEiTIsev rNsiTG!!
rpGOZmaimgn uplRzse naC DEoO LdGf
eIt uqHKC RBWOO xNf ujPMO SzRE HTL EOvd yAg
(^_^)
AWCTY HUOS RETP
hwn oeesd acsp nawyya
SpMycaeIesKyBorekn
D's mroyr, Ivam. I'e faardi I act'n od htta`
  .split`\n`
  .map(testCase => console.log(f(testCase)));
```
[Answer]
# [Python](https://docs.python.org/), 82 bytes
```
lambda s:S(r.lower(),t,S(r,t,s))
import re
S=re.sub
r='([A-Z])(.*?)'*2
t=r'\3\2\1'
```
[Try it online!](https://tio.run/nexus/python3#VY5NS8NAGITv@RVvT7tb2oD1VghS45IW464kgUCNhy3ZxJV8@e6mav98Gi9CLwPDPDNMBQEUU6PaU6nAblOKftN/a6Rs5Vazm9Uy5pl26NEBai8NUPt2PHkYEPq2Wx/fGfWXD4wsN54LkBT3xaa4I9OApnO0oqSJ@UcOEvu4XJB56j/AIZLHVpm27mAcmuRiNXQqhCfeS4jLqLqh9cHB@LV/DiF5zKWEH1HB@Pn6IiG9JBz2WQxcnkv43dU3PYEqr0OzBWGVXWvBTXaw@gworMmixd@l6Qo "Python 3 – TIO Nexus")
[Answer]
# QBasic, 229 bytes
```
LINE INPUT s$
FOR i=1TO LEN(s$)
c$=MID$(s$,i,1)
IF"@"<c$AND"[">c$THEN
IF u THEN MID$(s$,u,1)=c$:MID$(s$,i,1)=u$
u=-i*(u=0)
u$=c$
ELSEIF"`"<c$AND"{">c$THEN
IF l THEN MID$(s$,l,1)=c$:MID$(s$,i,1)=l$
l=-i*(l=0)
l$=c$
END IF
NEXT
?s$
```
### Strategy
We loop through the input string. When we encounter an uppercase letter, we store it and its position. The second time we encounter an uppercase letter, we use those stored values to swap it with the previous one. Same for lowercase.
(I was about to post a rather longer version that used an array, because I thought that QBasic strings were immutable. Then I stumbled across the fact that `MID$(strng$, index, length) = replacement$` works just fine. Live and learn.)
### Ungolfed + commented
```
LINE INPUT text$
FOR i = 1 TO LEN(text$)
  char$ = MID$(text$, i, 1)
  IF "A" <= char$ AND "Z" >= char$ THEN
    ' Uppercase
    IF upperIndex = 0 THEN
      ' This is the first of a pair of uppercase letters
      ' Store the letter and its index for later
      upperLetter$ = char$
      upperIndex = i
    ELSE
      ' This is the second of a pair of uppercase letters
      ' Put it at the position of the previous uppercase letter
      ' and put that letter at this letter's position
      MID$(text$, upperIndex, 1) = char$
      MID$(text$, i, 1) = upperLetter$
      upperIndex = 0
    END IF
  ELSEIF "a" <= char$ AND "z" >= char$ THEN
    ' Lowercase
    IF lowerIndex = 0 THEN
      ' This is the first of a pair of lowercase letters
      ' Store the letter and its index for later
      lowerLetter$ = char$
      lowerIndex = i
    ELSE
      ' This is the second of a pair of lowercase letters
      ' Put it at the position of the previous lowercase letter
      ' and put that letter at this letter's position
      MID$(text$, lowerIndex, 1) = char$
      MID$(text$, i, 1) = lowerLetter$
      lowerIndex = 0
    END IF
  END IF
NEXT i
PRINT text$
```
[Answer]
## C++11 (GCC), ~~154~~ 149 bytes
```
#include<algorithm>
[](std::string s){int*p,u,l=u=-1;for(auto&c:s)(c|32)-97<26U?p=&(c&32?u:l),~*p?(std::swap(c,s[*p]),*p=-1):*p=&c-&s[0]:0;return s;}
```
[Answer]
## Qbasic, ~~436~~ 408 bytes
```
LINE INPUT a$:b=len(a$):FOR a=1TO b:t$=MID$(a$,a,1)
IF"@"<t$AND"[">t$THEN
b$=b$+"U":u$=u$+t$
ELSEIF"`"<t$AND"{">t$THEN
b$=b$+"L":l$=l$+t$
ELSE b$=b$+t$
END IF:NEXT
FOR x=1TO b STEP 2:g$=g$+MID$(u$,x+1,1)+MID$(u$,x,1):h$=h$+MID$(l$,x+1,1)+MID$(l$,x,1):NEXT
FOR x=1TO b:t$=MID$(b$,x,1)
IF"U"=t$THEN
u=u+1:z$=z$+MID$(g$,u,1)
ELSEIF"L"=t$THEN l=l+1:z$=z$+MID$(h$,l,1)
ELSE z$=z$+t$
END IF:NEXT:?z$
```
*Saved one byte thanks to DLosc. Saved several more by changing handling of non-letter chars.*
This basically consists of three parts:
* Splitting the input into 3 strings (Uppercase, Lowercase, and a map (also holding the other chars))
* Flipping the uppercase and lowercase letters
* Using the map to (re)construct the output.
A more detailed explanation (note that this is of an earlier version of the code, but the principle still applies):
```
' --- Part I: Reading the input
LINE INPUT a$
'This FOR loop takes one character at a time
b=len(a$):FOR a=1TO b
' And checks in what category the character belongs
t$=MID$(a$,a,1):SELECT CASE t$
' For each group, char t$ is added to that group (u$ for uppercase, 
' l$ for lowercase. The map in b$ is updated with a U or L on this index,
' or with the non-letter char t$.
CASE"A"TO"Z":b$=b$+"U":u$=u$+t$
CASE"a"TO"z":b$=b$+"L":l$=l$+t$
CASE ELSE:b$=b$+t$
END SELECT:NEXT
' --- Part II: Swapping within case-groups
' Loop through u$ and l$ twp chars at a time, and add those chunks in reverse order
' to g$ and h$. Because mid$ doesn't fail past the end of a string (but returns ""), 
' this automatically compensates for odd-length groups.
FOR x=1TO b STEP 2:g$=g$+MID$(u$,x+1,1)+MID$(u$,x,1):h$=h$+MID$(l$,x+1,1)+MID$(l$,x,1):NEXT
' --- Part III: Read the map to put it all back together
FOR x=1TO b:t$=MID$(b$,x,1)
' See what group was in this spot, then read the next char from the flipped string.
' This keeps an index on those strings for the next lookup.
IF t$="U"THEN
u=u+1:z$=z$+MID$(g$,u,1)
ELSEIF t$="L"THEN l=l+1:z$=z$+MID$(h$,l,1)
' The map contains a non-letter char, just drop that in
ELSE z$=z$+t$
' And finally,display the end result.
END IF:NEXT:?z$
```
[Answer]
# [Perl 5](https://www.perl.org/), 48 + 1 (-p) = 49 bytes
```
for$p(qw/([a-z]) ([A-Z])/){s/$p(.*?)$p/$3$2$1/g}
```
[Try it online!](https://tio.run/##K0gtyjH9/z8tv0ilQKOwXF8jOlG3KlZTQSPaUTcqVlNfs7pYHyijp2WvqVKgr2KsYqRiqJ9e@/9/UYG7f1RuYmZuep5CaUFOUFVxqkJeorOCi2u@v4JPinvav/yCksz8vOL/ugUA "Perl 5 – Try It Online")
[Answer]
# PHP, ~~108~~ ~~93~~ 83 bytes
```
<?=preg_replace([$a="/([a-z])([^a-z]*)([a-z])/",strtoupper($a)],"$3$2$1",$argv[1]);
```
---
### Previous version (93 bytes)
```
<?=preg_replace(["/([a-z])([^a-z]*)([a-z])/","/([A-Z])([^A-Z]*)([A-Z])/"],"$3$2$1",$argv[1]);
```
Thanks to @user59178 for reminding me that [`preg_replace()`](http://php.net/manual/en/function.preg-replace.php) can take arrays of strings as arguments.
---
### The original answer (108 bytes)
```
$f=preg_replace;echo$f("/([a-z])([^a-z]*)([a-z])/",$r="$3$2$1",
$f("/([A-Z])([^A-Z]*)([A-Z])/",$r,$argv[1]));
```
The code is wrapped here to fit the available space.  
It can be executed from the command line:
```
$ php -d error_reporting=0 -r '$f=preg_replace;echo$f("/([a-z])([^a-z]*)([a-z])/",$r="$3$2$1",$f("/([A-Z])([^A-Z]*)([A-Z])/",$r,$argv[1]));' 'lLEhW OroLd!'
```
A 1-byte shorter version is possible on PHP 7 by squeezing the assignment of `$f` inside its first call:
```
echo($f=preg_replace)("/([a-z])([^a-z]*)([a-z])/",$r="$3$2$1",
$f("/([A-Z])([^A-Z]*)([A-Z])/",$r,$argv[1]));
```
---
Both solutions, with test cases and ungolfed versions can be found on [Github](https://github.com/axiac/code-golf/blob/master/unscramble-those-case-very-sensitive-strings.php).
[Answer]
# Mathematica, 96 bytes
```
s[#,r="([a-z])(.*?)([a-z])"]~(s=StringReplace[#,RegularExpression@#2->"$3$2$1"]&)~ToUpperCase@r&
```
A port of [Leo's Retina answer](https://codegolf.stackexchange.com/a/109122/56178), which uses regular expressions.
[Answer]
# [Python 2](https://docs.python.org/2/), 124 bytes
```
s=input();u=str.isupper
exec"r='';i=0\nfor c in s:r+=c[u(c):]or filter(u,s+s[::-1])[i^1];i+=u(c)\ns=r.swapcase();"*2
print s
```
Not as short as [my regex-based solution](https://codegolf.stackexchange.com/a/109143/12012), but I think it's still interesting.
[Try it online!](https://tio.run/nexus/python2#Fc7BToNAFIXhfZ/iwgYotrHGFWQWiqRtRMZUEhIpJgQGHEOH8V6m1r484vbkS84vLqIGtG17IiaVNqPrhYbRiGtJRmuBCzELG5njhJLdHlU7INQgFVCAPqsL49ZeUM5jK/tRoGtuyKciCFab0ivkx6YMpc/@0VERwzX9VLquSMw39vJuoVGqEWiaA5b3k9Mn8WcOHIeksZyFg3rL30@VPHUKjO4PVxKgqgie4oFD0mzb2Yj9COZ79xzB4THnHC5pC@br9YXD2/UQwy5LIObnBn4fulmnWOVdJANIqaKVSGOZ7UmcAVOS2daynD8 "Python 2 – TIO Nexus")
[Answer]
# [Bean](https://github.com/patrickroberts/bean), 83 bytes
Hexdump:
```
00000000 26 53 d0 80 d3 d0 80 a0 5d 20 80 0a a1 81 81 00  &SÐ.ÓÐ. ] ..¡...
00000010 23 81 01 20 80 0a a1 81 81 02 23 81 01 a8 db c1  #.. ..¡...#..¨ÛÁ
00000020 ad da dd a9 a8 db de c1 ad da dd aa bf a9 a8 db  .ÚÝ©¨ÛÞÁ.ÚÝª¿©¨Û
00000030 c1 ad da dd 29 a4 b3 a4 b2 a4 31 a8 db e1 ad fa  Á.ÚÝ)¤³¤²¤1¨Ûá.ú
00000040 dd a9 a8 db de e1 ad fa dd aa bf a9 a8 db e1 ad  Ý©¨ÛÞá.úÝª¿©¨Ûá.
00000050 fa dd 29                                         úÝ)
00000053
```
Equivalent JavaScript:
```
a.replace(/([A-Z])([^A-Z]*?)([A-Z])/g,'$3$2$1').replace(/([a-z])([^a-z]*?)([a-z])/g,'$3$2$1')
```
Explanation:
Implicitly taking the first line of input unformatted as `a` (since newlines can't be part of scrambled string), and implicitly outputs unscrambled string by sequentially replacing uppercase, then lowercase pairs.
### [Try demo here.](https://patrickroberts.github.io/bean/#h=JlPQgNPQgKBdIIAKoYGBACOBASCACqGBgQIjgQGo28Gt2t2pqNvewa3a3aq/qajbwa3a3Smks6SypDGo2+Gt+t2pqNve4a363aq/qajb4a363Sk=&i=bExFaFcgT3JvTGQh&f=0&w=1)
### [Try test suite here.](https://patrickroberts.github.io/bean/#h=JlfQgNPQgKB4IICIQKBdU9CA09CAoF0ggAqhgYEAI4EBIIAKoYGBAiOBASCAe1ZYgQOo28Gt2t2pqNvewa3a3aq/qajbwa3a3Smks6SypDGo2+Gt+t2pqNve4a363aq/qajb4a363SkK&i=bExFaFcgT3JvTGQhCnJwR09abWFpbWduIHVwbFJ6c2UgbmFDIERFb08gTGRHZgplSXQgdXFIS0MgUkJXT08geE5mIHVqUE1PIFN6UkUgSFRMIEVPdmQgeUFnCk5yYVdnQ2k6IE5zYXMtZU5FaVRJc2V2IHJOc2lURyEh&f=0&w=1)
[Answer]
# Ruby, 81 bytes
```
puts f=->(i,s){i.gsub /([#{s})([^#{s}*)([#{s})/,'\3\2\1'}[f[$*[0],'a-z]'],'A-Z]']
```
[Answer]
## JavaScript (ES6), 80 bytes
Based on **[Leo's Retina answer](https://codegolf.stackexchange.com/a/109122/58563)**.
```
s=>eval("s"+(r=".replace(/([A-Z])([^A-Z]*)([A-Z])/g,'$3$2$1')")+r.toLowerCase())
```
This works because the only uppercase characters in the code `.replace(/([A-Z])([^A-Z]*)([A-Z])/g,'$3$2$1')` are `A` and `Z`, which are used to describe the character ranges. This is precisely what we need to transform into lowercase in order to process the second pass.
### Test cases
```
let f =
s=>eval("s"+(r=".replace(/([A-Z])([^A-Z]*)([A-Z])/g,'$3$2$1')")+r.toLowerCase())
console.log(f("lLEhW OroLd!"));
console.log(f("rpGOZmaimgn uplRzse naC DEoO LdGf"));
console.log(f("eIt uqHKC RBWOO xNf ujPMO SzRE HTL EOvd yAg"));
console.log(f("NraWgCi: Nsas-eNEiTIsev rNsiTG!!"));
console.log(f("(^_^)"));
console.log(f("AWCTY HUOS RETP"));
console.log(f("hwn oeesd acsp nawyya"));
console.log(f("SpMycaeIesKyBorekn"));
console.log(f("D's mroyr, Ivam. I'e faardi I act'n od htta."));
```
[Answer]
# ES6 155 - 195 bytes
I know there's already a better answer, but I wanted to try without regex.
This one works on punctuation too, but that seems to violate the `(^_^)` test. In that case I have another `c()` function, given below.
```
f=(s)=>{d={};s=[...s];for(i in s){b=s[i];for(j in s)if(i<j&!d[i]&c(s[j])==c(b)){d[j]=1;s[i]=s[j];s[j]=b;break}}return s.join('')}
c=c=>~(c.charCodeAt()/32)
f("M I'o DaG") //> I'M a GoD
f("(^_^)")     //> )_^^(
c=c=>((c!=c.toUpperCase())<<1|c!=c.toLowerCase())||c.charCodeAt()
f("M I'o DaG") //> I'M a GoD
f("(^_^)")     //> (^_^)
```
### Explanation
```
f=(s)=>{
    d={};        //list of indexes already swapped
    s=[...s];        //string to array, stolen from above ES6 answer
    for(i in s){
        b=s[i];        //keep a note of what we are swapping
        for(j in s)        //iterate over the array again
            if( i<j & !d[i] & c(s[j])==c(b) ){
                        //only pay attention after we pass i'th
                        //only swap if this char hasn't been swapped
                        //only swap if both chars in same 'category'
                d[j]=1;        //note that the latter char has been swapped
                s[i]=s[j];
                s[j]=b;
                break        //avoid swapping on the same 'i' twice
            }
    }
    return s.join('')        //return as string
}
```
[Answer]
# [Perl 6](http://perl6.org/), 56 bytes
```
{for "A".."Z","a".."z" ->@c {s:g/(@c)(.*?)(@c)/$2$1$0/}}
```
Takes a string variable as an argument, and modifies it in-place so that after calling the lambda the variable contains the result.
Longer than it would be in Perl, because:
* The new regex syntax is more verbose, e.g. writing out the character classes would look like `<[A..Z]>` instead of `[A-Z]`.
* Regexes are first-class source code parsed at compile time, and a string can only be interpolated into them at run-time if it consists of a self-contained subregex (i.e. you can't interpolate a string into a character class).
* Explict `EVAL`, which would allow more flexibility, requires the golf-unfriendly `use MONKEY-SEE-NO-EVAL;` pragma.
On the plus side, an array in a `@` variable can be referenced directly in a regex, and is treated as an alternation.
---
# [Perl 6](http://perl6.org/), 65 bytes
```
{reduce ->$_,@c {S:g/(@c)(.*?)(@c)/$2$1$0/},$_,"A".."Z","a".."z"}
```
Functional version (outputs the result as the return value of the lambda).
[Answer]
# R, 343 Bytes
Terribly clumsy R solution:
```
f <- function(x) {
        y=unlist(strsplit(x,""))
        z=data.frame(l=ifelse(y %in% letters,0,ifelse(y %in% LETTERS,1,2)),s=y)
        l <- list(which(z$l==0),which(z$l==1))
        v <- unlist(l)
        for(j in 1:2) for (i in seq(1,ifelse(length(l[[j]])%%2==1,length(l[[j]])-2,length(l[[j]])-1),2)) l[[j]][i:(i+1)] <- rev(l[[j]][i:(i+1)])
        z[v,] <- z[unlist(l),]
        return(z$s)
    }
f("D's mroyr, Ivam. I'e faardi I act'n od htta.")
# [1] I ' m   s o r r y ,   D a v e .   I ' m   a f r a i d   I   c a n ' t   d o   t h a t .
```
[Answer]
## Python 2, 181 bytes
Much longer than it should be but anyway:
```
def F(s):
 for l in[i for i,c in enumerate(s)if c.isupper()],[i for i,c in enumerate(s)if c.islower()]:
  for a,b in zip(l[0::2],l[1::2]):s=s[:a]+s[b]+s[a+1:b]+s[a]+s[b+1:]
 print s
```
This first creates two lists: one of the indices of the uppercase characters and one for the lowercase characters. Each of these lists is looped through in pairs of indices, and the characters at those indices are switched.
I'll golf this down tomorrow, but for now it's time to sleep.
[Answer]
# [Pip](https://github.com/dloscutoff/pip), 28 bytes
```
Y[XLXU]aRy.`.*?`.y{Sa@0a@va}
```
Takes input as a command-line argument. [Try it online!](https://tio.run/nexus/pip#@x8ZHeETERqbGFSpl6CnZZ@gV1kdnOhgkOhQllj7////4ALfyuTEVM/UYu9Kp/yi1Ow8AA "Pip – TIO Nexus")
### Explanation
This is a regex solution, using the builtin regex variables `XL` (lowercase letters, ``[a-z]``) and `XU` (uppercase letters, ``[A-Z]``).
```
                              a is 1st cmdline arg; v is -1 (implicit)
Y[XLXU]                       Yank a list containing XL and XU into y
         y.`.*?`.y            Concatenate y, `.*?`, and y itemwise, giving this list:
                              [`[a-z].*?[a-z]`; `[A-Z].*?[A-Z]`]
       aR                     In a, replace matches of each regex in that list...
                  {        }  ... using this callback function:
                   Sa@0a@v     Swap the 0th and -1st characters of the match
                          a    and return the resulting string
                              Print (implicit)
```
When the second argument to `R` is a list, the replacements are performed in series; thus, the lowercase replacement and the uppercase replacement don't interfere with each other.
[Answer]
# [AWK](https://www.gnu.org/software/gawk/manual/gawk.html), ~~121~~ 129 bytes
```
BEGIN{FS=OFS=""}{for(a=1;a<=NF;a++){if($a~/[A-Z]/?U>0?p=U+(U=0):0*(U=a):$a~/[a-z]/?L>0?p=L+(L=0):0*(L=a):0>0){t=$a;$a=$p;$p=t}}}1
```
[Try it online!](https://tio.run/##Lc1bb4JAEAXg9/0VoyERalV8laLxgkpcWaMQUpvaTGRR6gW6i1o09K9bavpwMi/fOYOX3f3es0a2cxsuTFakXM5vnqkbtEgYCxXNpoEvpjM0sFrVblGoKvjTeOvWlu@NjtfWO4npVdWiobX0p@Ki1noArF0LQB@AVlX6D@gf0Nu6dktNBQ0FTSUxlMRM8zxv3u97am19YCKmQYmIZMSWB4wOmyOckv38KjkcsQ8DK2ZAg1FIuJ3C6Ws86cO85zMG304Ip8/ZlMHiOrdg7FKw2DmArLshjkB/049a4EiUNe5YkWtLfgbhyMgdlUpEXX2sNNL1@@4rjD22gLnlzsj2coSYcxkArmVS/L9kGZJFMs3WyG0uJ1kvFnx3JIOKhIOIM/EM9hkPdbArHEJEEURgF@W0UgwFsE1TrJNf "AWK – Try It Online") Note: Link has 8 extra bytes to allow multiline input
Usage is fairly typical, but does require a version of `AWK` that accepts an empty string as the field separator (most versions of `gawk` but I'm pretty sure the original `AWK` would fail :( )
It's very straightforward as it simply iterates over each character and checks if it's found one of that case before. If so, it swaps the characters and resets the checked index. On the learning side of things, I'd never used an assignment statement within an assignment statement in `AWK` before. For some reason it had never come up. :)
I might be able to shave a couple of bytes by saying to assign OFS and FS outside a `BEGIN` block via command-line assignment or similar, but it's "cleaner" this way.
*Adding the TIO link showed me that I had a transcription error that required 8 bytes to fix :( (I left out `0*(U=a):`)*
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 18 [bytes](https://github.com/tomtheisen/stax/blob/master/docs/packed.md#packed-stax)
```
âß:}\]ó☺æ■jφ╛jz/Φi
```
[Run and debug it](https://staxlang.xyz/#p=83e13a7d5c5da20191fe6aedbe6a7a2fe869&i=lLEhW+OroLd%21%0ArpGOZmaimgn+uplRzse+naC+DEoO+LdGf%0AeIt+uqHKC+RBWOO+xNf+ujPMO+SzRE+HTL+EOvd+yAg%0ANraWgCi%3A+Nsas-eNEiTIsev+rNsiTG%21%21%0A&a=1&m=2)
The general approach is regex-based.
* Two times do:
* Find all matches for `[a-z].*?[a-z]`.
* Swap the first and last character in matches.
* Invert case.
[Answer]
# [R](https://www.r-project.org/), ~~223~~ ~~163 bytes~~ 148 bytes
EDIT: -60 bytes by implementing a for loop
EDIT: -15 bytes from Giuseppe
```
u=utf8ToInt(scan(,''));for(i in c(65,97)){l=which(u%in%i:(i+25));x=sum(l|1)%/%2;u[l[1:(x*2)]]=u[c(matrix(l,2)[2:1,1:x])]};cat(intToUtf8(u,T),sep="")
```
[Try it online!](https://tio.run/##Dc5NC4IwGADgv2LC8H1rEA76muzYIRC6GB3Eg6zEwdxibjSofvvy/hwel1IQwQ/Hxl6Mh1n2BmhRIFaDdaAyZTIJ@x09HRA/WrxHJUcIRBmiOKgN2y0yijlMoL8lki1hVWh1W3KIa4ZdJ0IrYeq9UxE0ZdgyXtKSxw67XyV7D8r4xt6WAATaIJ2fL5HnmHJdn8d7dnW2fqzy9Ac "R – Try It Online")
Works by testing if character is a lowercase or uppercase, places them in a matrix, inverts the matrix to extract the values in a swapped format. Then output with `cat`. Try it online struggles with `scan(,'')` if the code is more than one line, hence the semicolons throughout the single line of code.
[Answer]
# [C (gcc)](https://gcc.gnu.org/), ~~212~~ ~~206~~ ~~205~~ 203 bytes
* Thanks to [ceilingcat](https://codegolf.stackexchange.com/users/52904/ceilingcat) for golfing ~~six~~ ~~seven~~ nine bytes.
```
#define I(a,b)if(S[j=i]/a&b/S[i]){for(;S[++j]<a|S[j]>b;);j<l?s[i]=S[j],s[j]=S[i]:0;}
i,j,l;f(char*S){char*s=calloc(l=-~strlen(S),1);for(i=~0;++i<strlen(S);)if(!s[i]){s[i]=S[i];I(65,90)I(97,'z')}puts(s);}
```
[Try it online!](https://tio.run/##PU9hb9owFPzOr3ik6mKX0LIP29SadFppRKPSZCJISNC0MokNzoKT2oEuMPrXWdJU/fL8dHfv7hx1l1F0PJ7EjAvJwEXUWmDBUTBPbBFe0C@Li2AuQrznmUIkmHc6Sdin/yo6vF4QTJJ@@lNXArtGLF0Nu9Zf9cihJazESglH0YqqswDv319tRzRNswildvdNFyplEgXY@opJnSDstx7pdET/kyF1m7Z@7/ARJELiou/frMsedtHlD8vcmfiQbwqNNCaHz7/MqutcCVlwZDzKU/0ou9dgWJUlr31bayokwvvWDBnpyFlNwVfZKG4buEZUPvRnlWK9lLDJ0/FOM5B0ALdO5sMoHvJGxtwCNi939wMY30x9H/56HDbJ7wcfgt3YgbvJCBx/G0P5a9kceIpOlwNxBZ6muss8R0xczbagPC0mw/ZHOnp6fsLNunqVkDGmY6CRzqsOr2VJGyrIH8qIMpfp@/ImU@yPbPBbU8NaZaWywN3S9Tm4JgNOqYoFuJVNYVaWMayKgp4b@HD8Dw "C (gcc) – Try It Online")
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~26~~ 23 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
2FÐlø€Ë≠āsƶ0KD2ôí˜‡<è.š
```
I/O as a list of characters.
[Try it online](https://tio.run/##yy9OTMpM/f/fyO3whJzDOx41rTnc/ahzwZHG4mPbDLxdjA5vObz29JxHDQttDq/QO7rw//9opRwlHSUfIHYF4gwgDgdiBSD2B@IiIM6HyqcAsaJSLAA) or [verify all test cases](https://tio.run/##HY2xTsJAGID3e4ofFjShxDASEwOlQqX0SFvT6IA56QHVtlfv2uIRTdTNuPgADrI56GaIs1UX34IXqY3jN3zfxwQ59WlxlVX1KE6TFkB1T9ZRFafJP5ZkF839/DHIPzZ3r/nD5v7561b8rHcG3Wb@nr/9Pm1uVrv5S@N7VVwf1D/Xe0VgaHMXMGeGV0E87uHjkPjhLII0DqyloBARFboaw2B4vSmiegLpRX@ggtVxMYZLcwrp2WiIwV5aGvQdAzSceSDbM2Ry4s5UvwWmIEKhpuY7uqAZcFP4Tq9SQVvjk/E2aruqcwT9Q2yDpTkjNF9EwCgVHpCJiMv/QkqC7HgoJ4TqVAxkh3F6HqFuTUDImeR10DMSNkCvUZgSwj0f9FJOamXIg3mSkEahKBFTArKUfw).
**Explanation:**
```
2F                # Loop 2 times:
  Ð               #  Triplicate the current character-list
                  #  (which will use the implicit input-list in the first iteration)
   l              #  Lowercase all letters of the top copy
    ø             #  Zip/transpose the top two lists; pairing them together, and swapping
                  #  rows/columns
     €Ë≠          #  Check for each pair whether they're NOT the same
                  #  (so uppercase characters that have now become lowercase)
  ā               #  Push a list in the range [1, length] (without popping)
   s              #  Swap so the mapped list is at the top again
    ƶ             #  Multiply each 1/0 by its 1-based index
     0K           #  Remove all 0s
       D          #  Duplicate this list of 1-based indices
        2ô        #  Split it into parts of size 2
          í       #  Reverse each part
           ˜      #  Flatten the list of swapped indices
            ‡     #  Transliterate the indices with the swapped indices in [1, length]
             <    #  Decrease each by 1 (because 05AB1E uses 0-based indexing)
              è   #  Index them into the current character-list
               .š #  And swap all cases (lowercase to uppercase, and vice-versa)
                  # (after the loop, the resulting character-list is output implicitly)
```
[Answer]
# Java 7, 117 bytes
```
String c(String s){String x="([a-z])(.*?)([a-z])",y="$3$2$1";return s.replaceAll(x,y).replaceAll(x.toUpperCase(),y);}
```
EDIT: Just noticed I have a similar answer as [*@Leo*'s Retina answer](https://codegolf.stackexchange.com/a/109122/52210), even though I've thought about it independently..
**Ungolfed:**
```
String c(final String s) {
  String x = "([a-z])(.*?)([a-z])",
         y = "$3$2$1";
  return s.replaceAll(x, y).replaceAll(x.toUpperCase(), y);
}
```
**Test code:**
[Try it here.](https://ideone.com/1aavz3)
```
class M{
  static String c(String s){String x="([a-z])(.*?)([a-z])",y="$3$2$1";return s.replaceAll(x,y).replaceAll(x.toUpperCase(),y);}
  public static void main(String[] a){
    System.out.println(c("lLEhW OroLd!"));
    System.out.println(c("rpGOZmaimgn uplRzse naC DEoO LdGf"));
    System.out.println(c("eIt uqHKC RBWOO xNf ujPMO SzRE HTL EOvd yAg"));
    System.out.println(c("NraWgCi: Nsas-eNEiTIsev rNsiTG!!"));
    System.out.println(c("(^_^)"));
    System.out.println(c("AWCTY HUOS RETP"));
    System.out.println(c("hwn oeesd acsp nawyya"));
    System.out.println(c("SpMycaeIesKyBorekn"));
    System.out.println(c("D's mroyr, Ivam. I'e faardi I act'n od htta."));
  }
}
```
**Output:**
```
hELlO WorLd!
prOGRamming puzZles anD COdE GoLf
tHe quICK BROWN fOx juMPS OvER THE LAzy dOg
WarNiNg: Case-sENsITive sTriNG!!
(^_^)
WATCH YOUR STEP
who needs caps anyway
MySpaceKeyIsBroken
I'm sorry, Dave. I'm afraid I can't do that.
```
]