Wyzwanie ogl-edocf

22

Wkład

ciągi losowe składające się ze znaków ASCII z zakresu .[32..126]

Wydajność

Dane wyjściowe uzyskuje się poprzez zastosowanie kolejnych obrotów do ciągu wejściowego.

Dla każdej litery ( [a-zA-Z]) w ciągu wejściowym, przechodząc od lewej do prawej:

  • jeśli litera jest pisana wielkimi literami, obróć wszystkie znaki przed nią o jedną pozycję w lewo
  • jeśli litera jest pisana małymi literami, obróć wszystkie znaki przed nią o jedną pozycję w prawo

Przykład

Dane wejściowe: „Cb-Ad”

  • Pierwsza litera to „ C ”. Powinniśmy wykonać obrót w lewo, ale przed tym „ C ” nie ma żadnej postaci . Nie ma więc nic do obracania.
  • Następna litera to „ b ”. Obracamy „ C ” w prawo. Ponieważ jest to jedna postać, pozostaje niezmieniona.
  • Znak „ - ” nie powoduje obrotu, ponieważ nie jest literą.
  • Następna litera to „ A ”. ObracamyCb- ” w lewo, co daje „ bC Ad”
  • Czwarta i ostatnia litera to „ d ”. Obracamy „ b-CA ” w prawo, co daje „ Ab-C d”

Dlatego oczekiwanym wynikiem jest „ Ab-Cd ”.

Zasady

  • Możesz przyjmować dane wejściowe jako ciąg znaków lub tablicę znaków - które mogą, ale nie muszą być takie same, w zależności od języka.
  • Możesz również wypisać tablicę znaków zamiast ciągu.
  • To jest

Przypadki testowe

"cbad" -> "abcd"
"ACBD" -> "ABCD"
"Cb-Ad" -> "Ab-Cd"
"caeBDF" -> "aBcDeF"
"aEcbDF" -> "abcDEF"
"ogl-edocf" -> "code-golf"
"W o,ollelrHd!" -> "Hello, World!"
"ti HIs SSta ET!" -> "tHis IS a tEST!"
Arnauld
źródło

Odpowiedzi:

5

Pyth, 21 20 bajtów

VQ=k+.>k-}NG}Nr1GN)k

Wypróbuj tutaj

Wyjaśnienie

VQ=k+.>k-}NG}Nr1GN)k
VQ                )      For each N in the input...
     .>k                 ... rotate k (initially '')...
        -}NG}Nr1G        ... by (N is lowercase) - (N is uppercase)...
    +            N       ... then append N...
  =k                     ... and update k.
                   k     Output the result.

źródło
Możesz użyć, .Uaby zmniejszyć wartość wejściową z 2. wartości. Pozwala to upuszczać =kod początku i )kod końca, ponieważ zarówno wejście, jak i drukowanie są niejawne. Pełny program: .U+.>b-}ZG}Zr1GZ- link
Sok
4

Python 2 , 100 98 95 bajtów

f=lambda s,p='':s and f(s[1:],[p[x:]+p[:x]+s[0]for x in[s[0].isupper()-s[0].islower()]][0])or p

Wypróbuj online!

TFeld
źródło
3

Galaretka , 14 bajtów

ØẠŒHċ€ḅ-N⁸ṙ;ð/

Monadyczny link akceptujący listę znaków, który daje listę znaków.

Wypróbuj online! Lub zobacz zestaw testowy .

W jaki sposób?

ØẠŒHċ€ḅ-N⁸ṙ;ð/ - Link - list of characters
             / - reduce by:
            ð  -   a dyadic chain:  1st call is f(L=1stCharacter, R=2ndCharacter)
               -                    ...then calls are f(L=previousResult, R=nextCharacter)
ØẠ             -     alphabet characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  ŒH           -     split in half = ["ABCDEFGHIJKLMNOPQRSTUVWXYZ","abcdefghijklmnopqrstuvwxyz"]
     €         -     for each:
    ċ          -       count occurrences (of R)
               -                          e.g.: 'W' -> [1,0]; 'c' -> [0,1]; '@' -> [0,0]
      ḅ-       -     convert from base -1             -1             1             0
        N      -     negate                            1            -1             0
         ⁸     -     chain's left argument (i.e. L)
          ṙ    -     rotate left by (the negate result)
           ;   -     concatenate R
Jonathan Allan
źródło
Nie znam zbyt dobrze galaretki, ale nie powinienem Irobić tego samego, co ḅ-w tym przypadku? Wydaje się, że tutaj działa , ale nie w twoim kodzie. Jestem trochę zdezorientowany dlaczego. Ponadto, czy istnieje polecenie wypychania całych list jako osobnych elementów na stos w Jelly (poczekaj, Jelly nie jest językiem opartym na stosie, prawda?)? W takim przypadku można użyć prostego odejmowania i jeśli nie mylę się, nie będziesz potrzebować negacji (podobnie jak w ostatniej edycji w mojej odpowiedzi 05AB1E).
Kevin Cruijssen,
1
Idaje listę - dodaj, ŒṘ aby zobaczyć pełną reprezentację . Tak ØẠŒHċ€IṪN⁸ṙ;ð/by działało.
Jonathan Allan,
Ach, ok, to ma sens. Dziękuję za wyjaśnienie. Fajna odpowiedź przy okazji, głosowałem już wczoraj. :)
Kevin Cruijssen
3

05AB1E , 18 17 16 14 bajtów

õsvy.uy.l-._y«

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

õ            # Start with an empty string
 sv          # Loop over the characters `y` of the input
   y.u       #  Check if `y` is an uppercase letter (1 if truthy; 0 if falsey)
   y.l       #  Check if `y` is a lowercase letter (1 if truthy; 0 if falsey)
      -      #  Subtract them from each other
       ._    #  Rotate the string that many times (-1, 0, or 1) toward the left
   y«        #  Append the current character `y` to the string
             # (And implicitly output the string after the loop)
Kevin Cruijssen
źródło
3

K4 , 43 33 bajty

Rozwiązanie:

""{.q.rotate[-/y in'.Q`A`a;x],y}/

Przykłady:

q)k)""{.q.rotate[-/y in'.Q`A`a;x],y}/"Cb-Ad"
"Ab-Cd"
q)k)""{.q.rotate[-/y in'.Q`A`a;x],y}/"ogl-edocf"
"code-golf"
q)k)""{.q.rotate[-/y in'.Q`A`a;x],y}/"ti HIs SSta ET!"
"tHis IS a tEST!"

Wyjaśnienie:

Iteruj po ciągu wejściowym, obracając poprzednie wyjście o 1, -1 lub 0 w zależności od jego pozycji na liście „a-zA-Z”.

""{.q.rotate[-/y in'.Q`A`a;x],y}/ / the solution
""{                            }/ / iterate (/) over, starting x as ""
                             ,y   / append y to
   .q.rotate[             ;x]     / rotate x by ...
                    .Q`A`a        / the lists "a..z" and "A..Z"
               y in'              / y in each (') alphabet?
             -/                   / subtract (-) over (/)

Uwagi:

  • -10 bajtów z inspiracją z rozwiązania 05AB1E
streetster
źródło
3

> <> , 45 43 bajtów

ii:2+7$.::&"`{"@)@(*?}"@["&::&@)@(*?{&!
ror

Wypróbuj online!

Fakt, że> <> ma rotację stosu, pomaga, ale nie trzeba sprawdzać wielkości liter.

Wyjaśnienie:

i    Get first inputted character
 i   Get second. This is to prevent errors from rotating an empty stack
  :2+7$.      Jump to the second line if that was EOF
        ::&   Create copies of the input and store one in the register
           "`{"@)@(*     Check if the char is lower case
                    ?}   If so rotate the stack
                      "@["&::&@)@(*?{   Rotate the other way if uppercase
                                     &  Push the new char
                                      ! Skip the first i instruction
Skip to the second line on EOF
ro      Reverse the stack and output
r r     Cancel out the first reverse
 o      Output the rest of the stack
Jo King
źródło
2

Haskell , 101 91 bajtów

-10 bajtów zainspirowanych odpowiedzią Curtisa Bechtela (użyj '@'<c,c<'['ponad elem c['A'..'Z']i odpowiedni zakres dla małych liter).

g(x:y)=foldl((<>pure).(!))[x]y
x@(a:b)!c|'`'<c,c<'{'=last x:init x|'@'<c,c<'['=b++[a]|0<1=x

Wypróbuj online!

Wyjaśnienie / Niegolfowany

Operator (!)pobiera niepusty ciąg, xna którym możemy dopasować wzór i znak:

x@(a:b) ! c
  | '`' < c, c < '{' = last x : init x  -- rotate x to the right by one
  | '@' < c, c < '[' = b ++ [a]         -- rotate x to the left by one
  | otherwise = x                       -- keep x as is

Teraz możemy zmniejszyć ogon wejścia od lewej do prawej, zaczynając od pierwszego znaku wejścia, używając:

\b a -> b!a ++ [a]
ბიმო
źródło
2

Haskell , 122 92 bajty

Dzięki BWO za sugestie! Dużo też zaoszczędziłem, przyjmując nieco inne podejście niż moja pierwotna odpowiedź.

l@(a:b)!c|'`'<c,c<'{'=last l:init l++[c]|'@'<c,c<'['=b++[a,c]|0<1=l++[c]
f(c:s)=foldl(!)[c]s

Wypróbuj online!

Curtis Bechtel
źródło
Możesz zamienić dopasowanie wzorca (#), użyć ,ponad &&, użyć [l!!0,c]ponad head l:[c], 1>0zamiast True, nie musisz liczyć f=i możesz założyć niepuste dane wejściowe, które oszczędzają l==[]wartę - oszczędzając Ci 13 bajtów: Wypróbuj online!
ბიმო
Btw. W zgłoszeniu użyłem isLoweri isUppergolfa , mam nadzieję, że nic ci się nie stanie, w przeciwnym razie cofnę edycję.
ბიმო
@BWO Dziękujemy za sugestie i śmiało!
Curtis Bechtel,
2

JavaScript (Node.js) , 116 102 bajtów

f=(s,i=1)=>s[i]?f(s.replace(RegExp(`^(.)(.{${i}})(?=[A-Z])|^(.{${i}})(.)(?=[a-z])`),"$4$3$2$1"),i+1):s

Wypróbuj online!

Oryginał ( 116 111 106B)

s=>Buffer(s).map((x,i)=>s=(t=s[S="slice"](i),i<2)?s:x>64&x<91?s[S](1,i)+s[0]+t:x>96&x<123?s[i-1]+s[S](0,i-1)+t:s)&&s

s=>Buffer(s).map((x,i)=>i<2|--x%32>25|x<64?s:s=[s[S="slice"](1,i)+s[0],s[i-1]+s[S](0,i-1)][+(x>95)]+s[S](i))&&s

s=>Buffer(s).map((x,i)=>!i|--x%32>25|x<64?s:s=(w=x>95,t=s.slice(1-w,i-w),w?s[i-1]+t:t+s[0])+s.slice(i))&&s

Shieru Asakoto
źródło
Prawdopodobnie jest to krótsze eval(`regex`)niż użycie konstruktora
Downgoat
@Downgoat Obawiam się, że tak nie jest, ponieważ przecięcia są potrzebne w przypadku eval(`regex`), więc -2 + 2 = 0, a zatem nie pomaga zmniejszyć liczby bajtów.
Shieru Asakoto,
@Downgoat Warto używać, eval()gdy używana jest co najmniej jedna flaga: eval('/./g')jest o 3 bajty krótsza niż RegExp('.','g').
Arnauld,
@Arnauld To prawda, ale nie używam tutaj flag.
Shieru Asakoto,
@ShieruAsakoto (Jasne. Mój komentarz skierowany był przede wszystkim do Downgoat, aby wyjaśnić, dlaczego nie warto tego tutaj robić).
Arnauld
2

Rubinowy , 51 bajtów

->s{w=[];s.map{|x|w.rotate!(x=~/\W/||?_<=>x)<<x};w}

Wypróbuj online!

Dane wejściowe i wyjściowe są tablicami znaków

Sztuczka:

Kod jest dość prosty, z wyjątkiem być może części rotacyjnej:

(x=~/\W/||?_<=>x)

x jest pojedynczym znakiem, który może być literą, pierwsze wyrażenie x=~/\W/zwraca, niljeśli jest literą, a 0 w przeciwnym razie. Jeśli jest to 0, skończyliśmy, jeśli nie, logiczne orsprawdza drugie wyrażenie: ?_<=>xzwraca -1 dla wielkich liter i 1 dla małych. Zatem obrót jest następujący:

  • -1 (1 w lewo) dla wielkich liter
  • +1 (1 po prawej) dla małych liter
  • 0 (brak obrotu), jeśli nie jest to litera
GB
źródło
2

Czerwony , 110 bajtów

func[s][p: s forall s[if all[(a: first s)>#"@"a < #"["][move p back s]if all[a >#"`"a <#"{"][move back s p]]p]

Wypróbuj online!

Wyjaśnienie:

f: func [ s ] [
    p: s                                ; store the starting position of the string in p
    forall s [                          ; iterate through the entire string
        a: first s                      ; store the current character in a
        if all [ a > #"@" a < #"[" ] [  ; if `a` is a uppercase letter
            move p back s               ; move the starting char to the position before current
        ]
        if all [ a > #"`" a < #"{" ] [  ; if `a` is a lowercase letter
            move back s p               ; move the character before the current one to the start
        ]
    ]
    p                                   ; return the string 
]
Galen Iwanow
źródło
2

Perl 6 , 47 bajtów

*.reduce:{|@$^a.rotate($^b~~/\w/&&'_'leg$b),$b}

Wypróbuj online!

Działa na szeregu znaków.

nwellnhof
źródło
Ach, wybrałbym używanie cmp i uc / lc, ale to dotyczy 49 bajtów
Jo King,
1
Cholera, 48 bajtów Prawie nadrobiłem zaległości
Jo King
2

Japt, 17 16 14 bajtów

Pobiera dane wejściowe jako tablicę znaków, generuje ciąg znaków

;rÏiXéCøY -BøY

Spróbuj


Wyjaśnienie

 rÏ                :Reduce by passing the current result (X) & the current element (Y) through a function
   i               :  Prepend to Y
    Xé             :  X rotated right by
;     B            :    Uppercase alphabet
       øY          :    Contains Y?
          -        :    Subtract
;          C       :    Lowercase alphabet
            øY     :    Contains Y?
Kudłaty
źródło
1

Java 10, 149 119 bajtów

s->{for(int i=1;i<s.length();)s=s.replaceAll("^(.)(.{"+i+"})(?=[A-Z])|^(.{"+i+++"})(.)(?=[a-z])","$4$3$2$1");return s;}

Port odpowiedzi @ShieruAsakoto JavaScript , więc upewnij się, że go głosujesz.

Wypróbuj online.

Wyjaśnienie:

s->{                          // Method with String as both parameter and return-type
  for(int i=1;i<s.length();)  //  Loop `i` in the range [1, length)
    s=s.replaceAll("^(.)(.{"+i+"})(?=[A-Z])|^(.{"+i+++"})(.)(?=[a-z])","$4$3$2$1");
                              //   Rotate the substring of [0, i] either left or right
  return s;}                  //  Return the modified input-String as result
Kevin Cruijssen
źródło
1

Stax , 32 bajty

éG7[Æ┐äZ▬Θε♫∙~╞ÉH╔u╬←J╛ü╢(┼▒uX)Ü

Uruchom i debuguj

B]s{c97 123:bsaa|)sc65 91:bsaa|(s+c}fd  #Full program, unpacked, implicit input
B]s                                     #Unons-left, singleton, swap top 2 of stack
   {c                                   #Copy iterative letter
     97 123                             #Put 97 and 123 on stack(lower case)
           :bsaa                        #Check if iterative letter is between range, swap orientation back to proper order
                |)                      #Rotate if the letter is within range
                  sc                    #Swap top 2 and copy top
                    65 91               #Put 65 and 91 on stack (Capitals)
                         :bsaa          #Check if iterative letter is between range, swap orientation back to proper order
                              |(        #Rotate if the letter is within range
                                s+c     #swap, concat and copy
                                   }fd  #remove duplicate of original answer after loop and implicitly print

Dużo wymiany stosów, które prawdopodobnie nie są potrzebne. Naprawdę chciałbym to bardziej obniżyć, ale miałem problemy z uporządkowaniem stosu. Może ktoś to zrozumie, jeśli się nudzi. Będę nad tym pracował.

Wielo
źródło
1

Attache , 69 bajtów

~Fold[{s'r.=_'sp;Rotate[s,&`-!Has&r[0]=>ALPHA'alpha]+r}@SplitAt]#Iota

Wypróbuj online!

Wyjaśnienie

Ogólny kształt

Funkcja wygląda ogólnie tak:

~Fold[{...}]#Iota

Który składa się {...}na każdym elemencie w zakresie od 0do #input - 1( Iota), zaczynając od danych wejściowych jako źródła.

Funkcja wewnętrzna

Następująca funkcja jest wywoływana jako f[building, index]i jest wywoływana z każdym indeksem od 0do #inputwyłącznego. @SplitAtwywołuje SplitAtte argumenty, dzieląc ciąg wejściowy index.

{s'r.=_'sp;Rotate[s,&`-!Has&r[0]=>ALPHA'alpha]+r}
{                                               }    anonymous function taking the split string
                                                     e.g.: ["cd-", "Adf!"]
      _'sp                                           concat the input with a space
                                                     e.g.: ["cd-", "Adf!", " "]
                                                     (this is to handle index = 0)
 s'r.=                                               `s` is the first member, and `r` is the second
           Rotate[s,                         ]       rotate `s` by:
                                  ALPHA'alpha          over uppercase and lowercase alphabets:
                        Has&r[0]=>                       test if r[0] is in each alphabet
                                                       e.g.: [true, false]
                    &`-!                               subtract the second from the first
                                                       e.g.: (true - false) = 1 - 0 = 1
                                                     s is rotated according to the following map:
                                                       uppercase =>  1
                                                       symbol    =>  0
                                                       lowercase => -1
                                              +r     append the right portion of the string

Zasadniczo ta funkcja obraca lewą część łańcucha zgodnie z pierwszym znakiem prawej części.

Conor O'Brien
źródło
1

Węgiel drzewny , 20 bajtów

FS≔⁺⭆ω§ω⁻⁺λ№αι№βιιωω

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

FS

Pętla nad znakami wejściowymi.

≔⁺⭆ω§ω⁻⁺λ№αι№βιιω

Mapuj dotychczasowy ciąg zebranych znaków, cyklicznie indeksując zebrane do tej pory znaki, zwiększając lub zmniejszając indeks, jeśli bieżący znak ma odpowiednio małe lub duże litery. To kończy obrót. Następny znak jest następnie konkatenowany, a wynik przypisywany z powrotem do łańcucha.

ω

Wydrukuj wynik.

Neil
źródło
1

R , 107 102 100 bajtów

Ogromny, ponieważ manipulacja sznurkiem R jest nieporęczna. Czy ktoś może dostać mniej niż 100?

-5 bajtów przy użyciu sztuczki „ustaw zmienne pętli na F, aby uniknąć inicjalizacji”.

-2 bajty, zakładając, że wszystkie znaki są drukowalne i używają 2*!k%%97>25raczej niż 2*k%in%97:122do testowania małych liter, stosując pierwszeństwo operatora.

function(x){for(k in u<-utf8ToInt(x))u[1:F-1]=u[(1:(F=F+1)+k%in%65:90-2*!k%%97>25)%%F];intToUtf8(u)}

Wypróbuj online!

J.Doe
źródło
1
Dołącz do nas (teraz jestem tylko ja ...) na czacie R golfa, aby podzielić się pomysłami! Domyślam się, że element permutacji jest tak krótki, jak to możliwe, przy takim podejściu, ale sam go nie wypróbowałem, nie jestem pewien.
Giuseppe,
1

Japt , 25 23 bajtów

Poddaję się, nie mogę tego skrócić

-2 bajty z @ETHproductions

£=¯Y éXè\a -Xè\A)+UsYÃU

£=¯Y éXè\a -Xè\A)+UsYÃU     Full program. Implicit input U
£                           map each char
 =                          set U equal to:
  ¯Y                        U sliced to current mapped value
    éXè\a -Xè\A)            and rotated left or right 1 char
                +UsY        append the non-sliced U value
                      ÃU    Output U    

Wypróbuj online!

Luis Felipe De Jesus Munoz
źródło
Niestety nie mogę znaleźć krótszego sposobu na zrobienie tego éXè\a -Xè\A:-( Możesz zaoszczędzić dwa bajty, zmieniając podwójną spację na a )i usuwając ©(domyślny przecinek oznacza, że Uwciąż jest wyprowadzany)
ETHproductions
Zaoszczędź kolejne 2 bajty, upuszczając ÃUi używając -hflagi.
Shaggy
1

Siatkówka , 67 64 58 bajtów

^
¶
+`(.*)(.)¶([a-z])|(.)(.*)¶([A-Z])|¶(.)
$2$1$3$5$4$6$7¶

-9 bajtów dzięki @Neil usuwając trzy niepotrzebne ?, które dodałem, a także niepotrzebne (.*)w innym przypadku.

Wypróbuj online lub sprawdź wszystkie przypadki testowe . (UWAGA: Dane wyjściowe z końcowym znakiem nowej linii. Nagłówek w pakiecie testowym służy do testowania każdej linii wejściowej jako osobnego przypadku testowego, a stopka służy do usunięcia tej linii końcowej w celu uzyskania bardziej zwartych wyników.)

Wyjaśnienie:

Przygotuj nowy wiersz przed wejściem:

^
¶

Kontynuuj wymianę, dopóki znajdziemy dopasowanie:

+`

Cała reszta to trzy różne kontrole połączone:

Jeśli znak zaraz po nowej linii jest małą literą: obróć wszystko przed nową linią jeden raz w prawo, a następnie dodaj ten znak i nową linię:

(.*)(.)¶([a-z])
$2$1$3¶

Jeśli znak zaraz po nowej linii jest wielką literą: obróć wszystko przed nową linią jeden raz w lewo, a następnie dodaj ten znak i nową linię:

(.)(.*)¶([A-Z])
$2$1$3¶

W przeciwnym razie (ani mała, ani wielka litera): wystarczy przesunąć raz nową linię w prawo w celu następnej „iteracji”:

¶(.)
$1¶

Te trzy powyższe kontrole są łączone z wyrażeniami regularnymi OR ( |) i większymi zamiennikami grup, aby działały jak if(lowercase) ... elseif(uppercase) ... else ...:

Kevin Cruijssen
źródło
Nie sądzę, że potrzebujesz ?s - jeśli nie ma jeszcze nic do obrócenia, nie ma znaczenia, czy jest list.
Neil
1
Ponadto, zastępując (.*)¶(.)ze $1$2¶można uprościć do zastąpienia ¶(.)z $1¶jak inne przechwytywania nie wpływa na wynik.
Neil
@Neil Ah, oczywiście dzięki. -9 bajtów tutaj! :)
Kevin Cruijssen
1

MATL , 20 bajtów

ttYo-ZS"X@q:&)w@YSwh

Wypróbuj online!

-4 bajty dzięki Luisowi Mendo.

Konwertuje wielkie / małe / nieliterowe na [-1,0,1] (pierwsza połowa programu). Stosuje zmianę biegów kolejno (druga połowa). Niszczę mózg, jeśli istnieje lepszy sposób na mapowanie wielkich / małych liter na [-1,0,1] (patrz druga wersja), a być może sposób na natychmiastowe odwrócenie łańcucha, aby pozbyć się dwóch wjest potrzebny do &).

Sanchises
źródło
1

C (clang) , 168 159 153 119 bajtów

g,i,j;f(char*a){for(i=0;a[j=i++];islower(a[i])?g=a[j],bcopy(a,a+1,j),*a=g:isupper(a[i])?g=*a,bcopy(a+1,a,j),a[j]=g:0);}

-26 dzięki @ceilingcat

Wypróbuj online!

Logern
źródło
Zaproponuj g=a[j=i++];islower(a[i])?bcopy(a,a+1,j)zamiasta[j=i++];islower(a[i])?g=a[j],bcopy(a,a+1,j)
ceilingcat
0

Pyth, 16 bajtów

em=+.>k-F}RGrBd2

Wypróbuj tutaj!

Wyjaśnienie:

em=+.>k-F}RGrBd2dQ    Autofill variables
 m               Q    for each d in Q (the input):
            rBd2       Take [d, swapcase(d)]
         }RG           Figure out which are in the lowercase alphabet (returns [1,0] for lowercase, [0,1] for uppercase, [0,0] for non-letters)
       -F              Fold on subtraction (1 for lowercase, -1 for uppercase, 0 for non-letter)
    .>k                Cycle the processed part (k) of the input right by ^ steps
   +            d      Add in the new character at the end
  =   k                Store new process step back into k (k starts as an empty string)
e                     Get the (e)nd step's output.
Steven H.
źródło