Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Inspired by this challenge (or, more specifically, by misreading it), I've come up with the following challenge:

Given an input string S, reverse the order of all uppercase characters, and all lowercase characters. Leave all non-letter characters in place. For instance:

Hello, World!

Note that the uppercase W (the first uppercase letter) was replaced with H (the last). Same goes for the lowercase letters: 'd' (the first) is swapped with e (the last), l (second) gets replaced with l (pen-ultimate) ... All the non-letter characters are left in place.

Input

  • Input is a string with only ASCII characters in the range 32-126.
  • Input is guaranteed to be at least 1 character long, and won't exceed your language's limit.

Output

  • That same string, with the characters swapped as described.

Additional rules

  • Standard loopholes are forbidden
  • Answer must be a full program or a function, not a snippet or a REPL-entry.
  • , shortest answer in bytes wins.

Test cases

A
A

Ok
Ok

OK
KO

Hello, World!
Wdlro, Holle!

0123456789
0123456789

The quick brown Fox jumps over the lazy doge
Feg odyza lehtr Tev ospmu jxon wor bkci uqeh

odd
ddo

racecar
racecar

EtOn Em OsN R AaToNsIsIhT!!1!
ThIs Is NoT A RaNsOmEnOtE!!1!
share|improve this question
    
You might want to include a 2-char testcase, my original solution failed on that at first. (Fixed at no cost by changing .+ to .*) – ETHproductions 16 hours ago

Retina, 19 bytes

Retina doesn't have a direct way to reverse a string, but we can do it by exploiting the sorting stage:

O^#`[a-z]
O^#`[A-Z]

Sort (O), reading them as numbers (#), and then reverse the ordering (^), of all the strings matching the given regex (lowercase letters for the first line, and uppercase letters for the second).

This works because when we try to read strings without numeric characters as numbers they get treated as 0, so all the characters have the same value for sorting. Since sorting is stable they are left in the same order, and reversing them returns the original string reversed.

Try it online!

share|improve this answer

Perl, 45 bytes

44 bytes of code + -p flag.

for$c(u,l){@T=/\p{L$c}/g;s/\p{L$c}/pop@T/ge}

Try it online!

Unicode characters classes \p{Lu} and \p{Ll} matches respectively uppercase and lowercase letters.
So /\p{L$c}/ will return the list of all upper (or lower) case letters (and store it inside @T).
And then, the regex s/\p{$c}/pop@T/ge will replace each (upper, then lower case) letter by the last letter of @T while removing it from @T.

share|improve this answer

MATL, 14 bytes

2:"t@Y2myy)Pw(

Try it at MATL Online

Explanation

        % Impicitly grab input as a string
2:      % Push the array [1, 2] to the stack
"       % For each value in this array
  t     % Duplicate the top element of the stack (S)
  @     % Get the current loop index
  Y2    % Load the predefined literal 1Y2 ('ABC...Z') on the first loop
        % and the predefined literal 2Y2 ('abc...z') on the second loop (M)
  m     % Create a logical array the length of S that is TRUE when a character is in the
        % array M and FALSE otherwise (B)
  yy    % Make a copy of both S and B
  )     % Grab just the letters of S that were in M using B as an index
  P     % Reverse this array
  w     % Flip the top two stack elements
  (     % Assign them back into the string
        % Implicit end of for loop and implicit display
share|improve this answer
    
Great job! I had 2:"tttXk>f)5MP(Yo for 17 bytes – Luis Mendo 15 hours ago

JavaScript (ES6), 92 bytes

s=>(F=(r,s)=>s.replace(r,([x],a,y)=>y+F(r,a)+x))(/[a-z](.*)([a-z])/,F(/[A-Z](.*)([A-Z])/,s))

There has got to be a way to take advantage of the similarity between the regexes...

Test snippet

let f =
s=>(F=(r,s)=>s.replace(r,([x],a,y)=>y+F(r,a)+x))(/[a-z](.*)([a-z])/,F(/[A-Z](.*)([A-Z])/,s))
<input style="width:500px" value="Wdlro, Holle!" oninput="O.value=f(this.value)"><br>
<input style="width:500px" value="Hello, World!" id=O disabled>

share|improve this answer
    
Does this assume that the function is assigned to a variable called f? Shouldn;t that be in the byte count? – steenbergh 16 hours ago
    
@steenbergh The function is anonymous, it can be called whatever you want it to be – Kritixi Lithos 16 hours ago
1  
@steenbergh Nope, it's an anonymous function which creates another function F then calls it recursively twice. The outer function doesn't actually call itself at any point. – ETHproductions 16 hours ago
    
Why do you use parentheses around .* in the regexes? – Luke 16 hours ago
    
@Luke to capture those characters (the a in ([x],a,y)=>) – ETHproductions 16 hours ago

JavaScript (ES6), 74 73 71 70 bytes

f=
s=>(g=r=>s=s.replace(r,_=>a.pop(),a=s.match(r)))(/[A-Z]/g,g(/[a-z]/g))
<input oninput=o.textContent=f(this.value)><pre id=o>

Edit: Saved 1 byte thanks to @Arnauld.

share|improve this answer
2  
I knew there was a better way... – ETHproductions 15 hours ago
    
I think you can save a byte with s=>(g=r=>s=s.replace(r,_=>a.pop(),a=s.match(r)))(/[A-Z]/g,g(‌​/[a-z]/g)) – Arnauld 9 hours ago

Jelly, 14 bytes

nŒlT,Ṛ$yJịŒsµ⁺

Try it online!

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.
    ,Ṛ$         Pair with its reverse. 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.
share|improve this answer

Python 2, 115 bytes

s=input();u=str.isupper
exec"r='';i=0\nfor c in s:r+=c[u(c):]or filter(u,s)[~i];i+=u(c)\ns=r.swapcase();"*2
print s

Try it online!

share|improve this answer
    
Can you replace \n with ;? – Tim 14 hours ago
    
Unfortunately, no. The argument of exec is parsed as usual Python code, so the for loop must be on its own line. – Dennis 13 hours ago

Perl 6, 75 69 bytes

{my @a=.comb;@(grep $_,@a).&{@$_=[R,] $_} for /<:Lu>/,/<:Ll>/;[~] @a}

How it works

  1. my @a=.comb;
    Split the string into characters, and store them in an array.

  2. for /<:Lu>/,/<:Ll>/
    For two regexes matching upper and lower-case letters, respectively...

    • @(grep $_,@a)
      Get a slice of all array entries matching the regex.

    • .&{@$_=[R,] $_}
      Assign the reverse of the slice to itself.

  3. [~] @a
    Concatenate the modified array to form a string again, and return it.


-6 bytes by stealing the idea to use Unicode classes instead of character ranges, from @Dada's solution.

share|improve this answer

Java (OpenJDK 8), 273 bytes

s->new String(new Error(){char[]o=s.toCharArray();char c;int b;{while(b++<2)
for(int l=0,r=o.length;l<r;l++){for(--r;r>l&&f(r);r--);for(;l<r&&f(l);l++);if(l<r){o[l]=o[r];o[r]=c;}}}
boolean f(int i){c=o[i];return b>1?!Character.isUpperCase(c):!Character.isLowerCase(c);}}.o)

Try it online!

share|improve this answer
    
You could save some bytes by making this into a lambda. s->new String... – NonlinearFruit 5 hours ago
    
@NonlinearFruit thank you! 294 -> 272, also fixed mistake when r an l was reused without initialization. – DmitrySamoylenko 47 mins ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.