Double rotation

Retina, 55 bytes

O$i`[a-m](?=.*([a-m]))?
$1
O$i`((?<![n-z].*))?[n-z]
$#1

Try it online!

Uses two sorting stages to rotate the first- and second-half letters separately.


05AB1E, 44 43 42 bytes

Оn2äø€J2ä©`ŠÃÁUÃÀVv®`yåiY¬?¦VëyåiX¬?¦Uëy?

Explanation

Generate a list of the letters of the alphabet of both cases. ['Aa','Bb', ..., 'Zz']

Оn2äø€J

Split into 2 parts and store a copy in the register.

2ä©

Extract the letters from the input that are a part of the 1st half of the alphabet, rotate it and store in X.

`ŠÃÁU

Extract the letters from the input that are a part of the 2nd half of the alphabet, rotate it and store in Y.

ÃÀV

Main loop

v                         # for each char in input
 ®`                       # push the lists of first and second half of the alphabet
   yåi                    # if current char is part of the 2nd half of the alphabet
      Y¬?                 # push the first char of the rotated letters in Y
         ¦V               # and remove that char from Y
           ëyåi           # else if current char is part of the 1st half of the alphabet
               X¬?        # push the first char of the rotated letters in X
                  ¦U      # and remove that char from X
                    ëy?   # else print the current char

Try it online!

Note: The leading Ð can be omitted in 2sable for a 41 byte solution.


Javascript (ES6), 155 142 138 bytes

s=>(a=[],b=[],S=s,R=m=>s=s.replace(/[a-z]/gi,c=>(c<'N'|c<'n'&c>'Z'?a:b)[m](c)),R`push`,a.unshift(a.pop(b.push(b.shift()))),s=S,R`shift`,s)

Edit: saved 3 4 bytes by using unshift() (inspired by edc65's answer)

How it works

The R function takes an array method as its parameter m:

R = m => s = s.replace(/[a-z]/gi, c => (c < 'N' | c < 'n' & c > 'Z' ? a : b)[m](c))

It is first used with the push method to store extracted characters in a[] (first half of alphabet) and b[] (second half of alphabet). Once these arrays have been rotated, R() is called a second time with the shift method to inject the new characters in the final string.

Hence the slightly unusual syntax: R`push` and R`shift` .

Demo

let f =
s=>(a=[],b=[],S=s,R=m=>s=s.replace(/[a-z]/gi,c=>(c<'N'|c<'n'&c>'Z'?a:b)[m](c)),R`push`,a.unshift(a.pop(b.push(b.shift()))),s=S,R`shift`,s)

console.log("Hello_world", "=>", f("Hello_world"));
console.log("codegolf", "=>", f("codegolf"));
console.log("HELLO_WORLD", "=>", f("HELLO_WORLD"));

Tags:

Code Golf