[Question]
  [
*Please note the special scoring for this challenge.* 
Given a non-empty string made of `a-z`, output the string immediately before it in the [shortlex order](https://en.wikipedia.org/wiki/Shortlex_order).
**Shortlex order**
We enumerate strings in shortlex order by first listing the strings of length 0, then those of length 1, then length 2, and so on, putting them in alphabetical order for each length. This gives an infinite list of all strings. Said a bit differently, this sorts strings by length, tiebroken alphabetically.
For strings `a-z` as used in the challenge, this list goes (abridged):
```
(empty string)
a
b
c
...
z
aa
ab
...
az
ba
bb
...
zy
zz
aaa
aab
...
```
**Scoring**
Answers will be compared in shortlex order, with earlier being better.
Like in code golf, fewest bytes wins, but there's a tiebreak for same-length answers in favor of coming first alphabetically. This means that you'll want to further "golf" your answer to use characters with lower code points where this doesn't hurt its length. Characters nearer to the start are more important.
For non-ASCII languages, answers are treated as a sequence of bytes. Use the byte order of the code page to compare characters, not their UTF encoding. 
For your answer's header, you can just put the code's length and say when you've outgolfed a same-length answer in the same language. You could also put the code's position in shortlex order if that number is not too long.
**Input and output**
The input string will be between 1 and 10 characters long, and consist only of letters `a-z`. As per site defaults, you may do I/O with strings as lists of characters or code points. The letters should be lowercase (code points 97-122).
**Test cases**
The first output is the empty string.
```
a -> 
c -> b
z -> y
aa -> z
az -> ay
ba -> az
aaa -> zz
zaa -> yzz
golf -> gole 
bzaaaaaaaa -> byzzzzzzzz
zzzzzzzzzz -> zzzzzzzzzy
```
**Related:** [Smaller Strings in Printable ASCII base](https://codegolf.stackexchange.com/q/200967/20260), [Counting in bijective base 62](https://codegolf.stackexchange.com/questions/79304/counting-in-bijective-base-62)
  
[Answer]
# [Haskell](https://www.haskell.org/), ~~64~~, ~~63~~, ~~56~~, 55 bytes
* `c` is an infinite list of all strings composed of `97..122` in shortlex order.
* `\x y -> last$fst$span(/=x)y` gives the predecessor of `x` in `y`
```
a b=last$fst$span(/=b)c
c=[]:[d++[e]|d<-c,e<-[97..122]]
```
[Try it online!](https://tio.run/##TY3LasQwDEX38xUizCJmkpTOprSMN6X9CuOFktitqR/BdhYJ/fdUTmEyCyHOuVfoG9OPsnYzbgoxwwdm7N6Nnv2QQ4S2Ba/UqEbQRFmlnDaEnltM@axp0oS@fuI9G04DF/JNjJeLUPJ3vLVDo26teH3puufrVcrNofHAYYrGZzifANBaqOnRHOMCNecMOtAmpgy1wwly@PSzI4c0RegYXFGM7ecC6gqrpqoYQUMwEPR3WomWO2FprgeWFI@4LzE@5P/9Q6y7WB7MV7CaFC21O7n9AQ "Haskell – Try It Online")
* 1 byte saved by using code points: `[97..122]` vs. `['a'..'z']`
* 9 bytes saved by [ovs](https://codegolf.stackexchange.com/users/64121/ovs)
* 1 bytes saved by [Laikoni](https://codegolf.stackexchange.com/users/56433/laikoni)
## Shortlex optimality
To get the lowest-ordered version of this code:
* Each variable is chosen to be the smallest, front-to-back
* The two lines are sorted (`' ' < '='`)
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), 8 bytes
```
ef!-TGrN
```
[Try it online!](https://tio.run/##K6gsyfj/PzVNUTfEvcjv/3@lxEQlAA "Pyth – Try It Online")
Throws an error for input `a`, but outputs nothing to STDOUT, which is technically the correct output.
**Explanation**
```
ef!-TGrN
      rN   Build a string range from the string '"' to the implicit input
 f         Filter for strings of this range satisfying:
  !         - the string becomes empty...
   -TG      - ...when all lowercase letters are removed
e          Take the last element   
```
*Note*: `N` was used to start the range rather than `d` or `k` since it has a lower codepoint.
[Answer]
# [Ruby](https://www.ruby-lang.org/) `-pl`, ~~29~~ 13 bytes
```
*,$_=*?a...$_
```
[Try it online!](https://tio.run/##KypNqvz/X0tHJd5Wyz5RT09PJf7//0SuZK4qrsRErsQqriQgCWRVAXF6fk7av/yCksz8vOL/ugU5AA "Ruby – Try It Online")
Ironically, this task is essentially the opposite of Ruby's `next` (or alternatively `succ`) method on strings, however this potential `previous` method is not available out of the box. Therefore, to take advantage of existing functionality we have to loop through the range of strings (which is constructed using `succ`) from `"a"` all the way to the input (non-inclusive), and take the last position. Obviously, this will be too slow for the longer test cases.
[Answer]
# [Python 3.8](https://docs.python.org/3.8/), ~~67~~ 65 bytes
*Thanks @xnor for helping me get my shortlex score down!*
```
A=lambda	B:(C:=B.pop())>97and	B+[C-1]or	A(B)+[122]if	B>[97]else[]
```
[Try it online!](https://tio.run/##TU7dboMgFL6WpyBcYaom7S66mmiifQzjBSquLAgEWDJs@uwO0C37Ljjf3zlBOfuQ4u1d6W1rKk6WYSJJW@J7WbWFkgqnaX27EjEl7am75@de6qTBbXrqzpdLz@akrbvbtafc0K7f2KKkttA4A2apIWeCQiaCLoydmCgBNBmk34qOFlZwIQobq32mmcpivTCKM4tRXqM09W3f4sxYHKpST5kJrqbmi4cDDTb/JULFp2QilseHzo4krCjNhMUzeu7WC3bP37Xq@NCrR@lGYF5DMIZ3AGsYDpBoroBETRwYokG8c0QrWHfmPP2QfA7cTwrB4JMd8aYv7ADrH/YTB9wP "Python 3.8 (pre-release) – Try It Online")
A recursive function that takes in a list of code points, and returns a list of code points. 
Note that all spaces are replaced with tabs for smaller shortlex score.
Let `C` be the last character of the string, and `B` be the prefix. If `C == "a"`, then the result is `A(B) + "z"`. If `C != "a"`, then the result is `B + "{C-1}"`.
The base case is when the string is `""` or `"a", in which case the function returns the empty string.
---
Same idea, but this function takes in and returns proper strings.
# [Python 3.8](https://docs.python.org/3.8/), ~~73~~ 72 bytes
```
A=lambda	B:B>"a"and[B[:-1]+chr(C:=ord(B[-1])-1),A(B[:-1])+"z"][97>C]or""
```
[Try it online!](https://tio.run/##PUzLasMwEDx3v2LRSSJ2IPTQ1mCDnc8wPsiPNAJbEpIClUK@3ZUtt3PYnRejvbsr@f6pzbrW5cyXfuRvTdFUhBMux7Zpi/zSnYa7odeiVGakTRsNll9YVtOUshMJpGu/Pqprpwwhq1i0Mg6tt3BTBmchJxRy02frRiELQJvh9KOnwWGJC9fUOhMzI3S2189Wz8JRkleEMUAz2ce8VWtqo9RGSEdv5Jn8F7bPv0Z5zL46wlaOeYUwbLeHsD0PfDcD8F1zD/1u8OgcUYCQmI/0W823jcc/IfQxSdg3YyEBwj/SxAH/Cw "Python 3.8 (pre-release) – Try It Online")
[Answer]
# [Retina 0.8.2](https://github.com/m-ender/retina/wiki/The-Language/a950ad7d925ec9316e3e2fb2cf5d49fd15d23e3d), 22 bytes
```
(?=a+$)^a
T`l`zl`.a*$
```
[Try it online!](https://tio.run/##K0otycxL/K@q4Z7wX8PeNlFbRTMukYsrJCEnoSonQS9RS@X//0SuZK4qrsRErsQqriQgCWRVAXF6fk4aVxKQBQFcVXAAAA "Retina 0.8.2 – Try It Online") Link includes test cases. Explanation:
```
(?=a+$)^a
```
Remove one of the `a`s if all of the letters are `a`s. The lookahead is naturally placed before the anchor as it has a lower ASCII code.
```
T`l`zl`.a*$
```
Cyclically decrement any the trailing `a`s and the previous letter.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~14~~ 13 bytes
```
LØaṗṪṖṭƊði’ị⁸
```
[Try it online!](https://tio.run/##y0rNyan8/9/n8IzEhzunP9y56uHOaQ93rj3WdXhD5qOGmQ93dz9q3PH/4e4th9sfNa2J/P8/kSuZq4orMZErsYorCUgCWVVAnJ6fk8aVBGJVAQEA "Jelly – Try It Online")
*-1 byte thanks to Jonathan Allan reminding me of the Cartesian power builtin.*
A ~~new~~ different approach using raw enumeration instead of math. `LØaṗṖL¦ði’ị⁸` is a byte shorter, but doesn't correctly produce the empty string for some reason. It's not quite so efficient as the first solution, so I've abridged the longer test cases...
```
 Øaṗ             Take the Cartesian product of the lowercase alphabet with itself
L                a number of times equal to the length of the input.
    Ṫ            Take the last element of the product (e.g. "zzzz"),
     Ṗ           remove its last element ("zzzz" -> "zzz"),
      ṭƊ         and re-append it to the product.
        ð        Given that product and the original input,
         i       find the input's index in the product,
          ’      subtract 1,
           ị⁸    and index back into the product.
                 Since Jelly uses modular 1-indexing, if the input is the least
                 string of its length, its index of 1 will decrement to 0, which
                 then maps it back to the end of the enumeration, which has been
                 truncated appropriately.
```
# [Jelly](https://github.com/DennisMitchell/jelly), 21 bytes
```
O_96µJṚ’26*×µS’ḃ26ịØa
```
[Try it online!](https://tio.run/##y0rNyan8/98/3tLs0FavhztnPWqYaWSmdXj6oa3BQObDHc1GZg93dx@ekfj/4e4th9sfNa2J/P8/kSuZq4orMZErsYorCUgCWVVAnJ6fk8aVBGRBAFcVHAAA "Jelly – Try It Online")
There's probably a shorter conversion from bijective base 26 out there, but I figured I may as well write my own before taking someone else's.
[Answer]
# [Factor](https://factorcode.org/), 115 bytes
```
: а ( s -- s ) >array [ 96 - ] map reverse
dup length [0,b] [ 26 swap ^ ] map [ * ] 2map
sum 1 - bijective-base26 ;
```
A naive implementation using `bijective-base26` which does half the work. This solution doesn't work in TIO, because it apparently doesn't include the `html-help` dictionary.
Here's a screenshot from my desktop Factor Listener:
[![Shortlex predecessor](https://i.stack.imgur.com/Ju3BI.png)](https://i.stack.imgur.com/Ju3BI.png)
[Answer]
# JavaScript (ES6), ~~65 64~~ 62 bytes
I/O: array of code points
```
$=>$.reduceRight((A,B,C)=>!C&($=$&&--B<97)?A:[$*26+B,...A],[])
```
[Try it online!](https://tio.run/##XY/BToQwFEX38xW1aZhWoZO40GgsBvgDXRIWpVMYJgydlGoCP491aEG5u3fuu/flnfk374Vuribq1FFOFZsQixHV8vgl5EdTnwzGSZiGGWHxXRZgxFAQRFH69vJM3pPXHN0/Pj2kIaU0KcK8IJORvQEM9IDFQKiuV62krapxhXO71Bf0wq9Y3FwqTlxn9mxiMCFkdT6NbrqaVlpdMreChV04q6bD@z0hu93vGQw5BF4EHA7AYbHBpePjhg@@Zu258dHz8T/nPlBuAnxJrFVzkzfGjTEsTq3aCv5x7Cz9I6WNzYLzIzY2y9cugu6e0zD9AA "JavaScript (Node.js) – Try It Online")
### Commented
```
$ =>                  // $[] = input array, reused for the carry
  $.reduceRight(      // for each
    (A, B, C) =>      // code point B at position C, using A[] as the accumulator:
    !C &              //   is it the leading 'digit'?
    ( $ = $ && --B    //   if the carry is set, decrement B
               < 97 ) //   and set it again if the result is 96 (just below 'a')
    ?                 //   if this is the leading 'digit' and the carry is set:
      A               //     leave A[] unchanged
    :                 //   else:
      [ $ * 26 + B,   //     prepend B if there's no carry or B + 26 otherwise
        ...A ],       //     (which gives 122, or 'z')
    []                //   initialize the accumulator to an empty array
  )                   // end of reduceRight()
```
[Answer]
# [Python 2](https://docs.python.org/2/), 81 bytes
```
A="";B=1
for C in input()[::-1]:A=chr((ord(C)-97-B)%26+97)+A;B*=C<"b"
print A[B:]
```
[Try it online!](https://tio.run/##PU3BDoIwDL3vKxoSsyHhAAeN0x0G0asXb8YDjClEwpZmROXnccPEl772vbZp7ce1ZshnZRotKKWzFFG0L0RG7gahhG7wYUfH4ivnaXbjUqgWGTPYsDJOd9u0iFf5Jtlt40Tui7UoD1EdEYvd4EBeC36b/VVCXm3Xa7jgqDkBcPgJBUC/tYLwmwSttHVwPJ@OiAZ/CzXq6jnTihKqPCfPKpgqqHpRi5@W/DD9PfS9@yFM/qBf "Python 2 – Try It Online")
72 bytes with lists of code points as input and output:
```
A=[];B=1
for C in input()[::-1]:A=[(C-97-B)%26+97]+A;B*=C<98
print A[B:]
```
[Try it online!](https://tio.run/##lU09D4IwFNz7K95iQJGEYiK0yABEVxe3poNiDUQDpClRfj2@xo@wOJj0Xa9313vdYKq2CceyPavUcZwxS4VM8pSSS6uhgLrB0/XGnQvOfSo5@m7hs8jP57Nw7bFIelmSL9Jiw2LS6boxkImcyxHLCLlX9U3BQfeKEwCjB3sBqIcqwa4klpeqM7Dd77Zat/oVOGl1vI4C24lgDIGGoaXREl4akrcUT6Svj970FawwTilCEFv4fJzEfs2n7A@QTw "Python 2 – Try It Online")
[Answer]
# [J](http://jsoftware.com/), ~~39~~ ~~36~~ ~~35~~ ~~31~~ 26 bytes
*-5 when using codepoints*
```
*/@:=&97}.<:&.(26#.2,-&97)
```
[Try it online!](https://tio.run/##y/qvpKeepmBrpaCuoKNgoGAFxLp6Cs5BPm7/tfQdrGzVLM1r9Wys1PQ0jMyU9Yx0dIECmv81/6cpGKuVAnUlqnPBmMkIZhWCmYikIhFJPAlZHFlRFTInPT8nDUkPUA4CkJTDgboCAA "J – Try It Online")
### How it works
```
*/@:=&97}.<:&.(26#.2,-&97)
                     -&97  a->0,b->1,..
               26#.2,      append 2 and convert from base 26
          <:&.(          ) execute right side, then decrement,
                           then inverse of right side
               26#.2,      convert to base 26 and drop the 2
                     -&97  convert back to string
*/@:=&97                   does input string only contain a's?
        }.                 drop 0 or 1 letters
```
[Answer]
# [Haskell](https://www.haskell.org/), 56 bytes
```
a.b.a
a=reverse
b"a"=""
b('a':a)='z':b a
b(a:b)=pred a:b
```
[Try it online!](https://tio.run/##VY5NCsIwEIX3PcUQhLZQe4BC3HgBl4KKvNRUxVglFdEe3jhNSqNvk3xv3vyc0F20Ma473ezD6Nf@bvWBJG0dSlUigbT6qW2nEyUgpBCJylKkFXKZ9mmlCGygUrn0jfxzV5xbnnC35/ZBM4IxlG0zFCqn@YL@F4GkJC4kRBvKeENBQuRMBVM9kJqwH/A9IXy4j@zriAHlA/hJjC3R6YPz/rGON9MMHr86juJgkD@J80Fx0KSwYVQ4Zuc@dWNw7Nx8vVytvg "Haskell – Try It Online") The identifier names are a bit confusing (i.e. `a` appears as the current character, the rest of the string, and as shorthand for `reverse`) in order to use low code points. 
Currently beats the [other Haskell](https://codegolf.stackexchange.com/a/206036/56433) answer, though I already submitted an one byte improvement there which will put it into the lead again.
[Answer]
# [K (ngn/k)](https://bitbucket.org/ngn/k), 35 bytes
```
{`c$97+1_26\-1+26/2,{(~+/x)_x}x-97}
```
[Try it online!](https://tio.run/##y9bNS8/7/z/NqjohWcXSXNsw3sgsRtdQ28hM30inWqNOW79CM76itkLX0rz2f3WFjpKCrp2Ckk6aQ0WtuoaOlVKikjWQTAaTVUrWSomJIALESgKzwPwqMJmen5MGEgfyIAAkAwdKmlz/AQ "K (ngn/k) – Try It Online")
Strongly inspired by @xash's [J solution](https://codegolf.stackexchange.com/a/206039/75681) - don't forget to upvote it!
[Answer]
# [PHP](https://php.net/), 35 bytes
```
for($a=a;$a!=$argn;$b=$a++);echo$b;
```
[Try it online!](https://tio.run/##K8go@G9jXwAk0/KLNFQSbROtVRIVbVUSi9LzrFWSgAxtbU3r1OSMfJUk6///0/Nz0v7lF5Rk5ucV/9d1AwA "PHP – Try It Online")
who knew strings incrementing would serve one day? Too bad decrementing doesn't work..
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 10 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
āAδã˜s¡нθJ
```
[Try it online](https://tio.run/##AR8A4P9vc2FiaWX//8SBQc60w6PLnHPCodC9zrhK//9iemFh) or [verify all (short) test cases](https://tio.run/##yy9OTMpM/V9Waa@k8KhtkoKSfeX/I42O57YcXnx6TvGhhRf2ntvh9V/nf7RSopKOUjIQVwFxIoiTCGIlgVlgfhWYTM/PSQOJQ3hVQKAUCwA). (Times out for any test cases with a length above 5 due to the `ã` builtin.)
**Explanation:**
```
ā           # Push a list in the range [1, (implicit) input-length] (without popping)
 A          # Push the lowercase alphabet
  δ         # Apply double-vectorized:
   ã        #  Take the cartesian product
    ˜       # Flatten this list of lists
     s      # Swap so the input is at the top of the stack
      ¡     # Split this list of strings on the input
       н    # Only leave the first list
        θ   # And leave the last string of that first list
         J  # Join (for the edge case 'a', which will result in an empty list [])
            # (after which it is output implicitly as result)
```
NOTE: In this solution I'm alternatively able to change the `н` to `ć`/`¬`; `θ` to `¤`; and/or `J` to `»` without changing the functionality. However, all of those would only negatively effect the score, since `нθJ` are earlier in the [05AB1E encoding](https://github.com/Adriandmen/05AB1E/wiki/Codepage).
[Answer]
# SimpleTemplate, 25 bytes
I loved PHP's feature where incrementing `'a'` woud give `'b'`, and incrementing `'z'` would give `'aa'`.
So, since very early in the creating, I've decided to emulate that functionality, but PHP doesn't support *decrementing*.  
That had to be implemented manually, a long time ago...
---
Anyway, this is the code for the task:
```
{@incby-1argv}{@echoargv}
```
The code is incredibly simple: Increment all values in `argv` by -1 (decrement) and output it (without a separator).
An ungolfed version of the code isn't much different:
```
{@inc by -1 argv}{@echo argv}
```
(Note: `argv` is the default variable that contains all arguments passed, both to the script as well as to a function. Converting to a function is trivial.)
---
You can try it on: <http://sandbox.onlinephpfunctions.com/code/05d4f13a1d27480d119e516c446b9d001d1111d8>
[Answer]
# perl -M5.010 -nl, 46 bytes
```
$"=a;say/^$"$/?"":do{{$,=$"++;/^$"$/||redo}$,}
```
[Try it online!](https://tio.run/##K0gtyjH9/19FyTbRujixUj9ORUlF315JySolv7paRcdWRUlb2xoiWlNTlJqSX6uiU/v/f2IiVyJXRWUVV0FhYuK//IKSzPy84v@6vqZ6BoYG/3XzcgA "Perl 5 – Try It Online")
Very slow. Starting with `a`, it iterates over all the strings consisting of lower case letters, in shortlex order. If it matches the input, it prints the previous string. Some bytes are wasted to deal with the input of `a`, which should return the empty string.
[Answer]
# [Brachylog](https://github.com/JCumin/Brachylog), 19 bytes
```
{{∧Ẓ∋}ᵐ|b↰}ᶠs[?,.]∧
```
[Try it online!](https://tio.run/##SypKTM6ozMlPN/pfXa6koGunoFRu/6htw6Ompoe7OmtPL/pfXf2oY/nDXZMedXTXPtw6oSYJKFv7cNuC4mh7Hb1YoNz//9FKiUo6SslAXAXEiSBOIoiVBGaB@VVgMj0/Jw0kDuRBAEgGDpRiAQ "Brachylog – Try It Online")
I expect to be able to outgolf this.
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 85 bytes
Works backwards from the end, overwriting the string as it goes along. If the previous digit borrowed (which the first character processed always does), then decrement the current digit, wrapping if required. If the final digit processed wrapped, then return the next character in the string.
```
A,B,C;D(char*E){for(A=1,B=strlen(E);B--;E[B]=(A=C<97)?B?122:0:C)C=E[B]-A;return E+A;}
```
[Try it online!](https://tio.run/##VU5BasMwELzrFYtLipTKJcmlNIodbMevKD3IsuQIHDlo7RYc8vW6EpRAB3aZnVmGUWmn1LIUvOSVOFF1ln5ds5sZPC2yLS8zHH2vHa2ZKNNU1B/lZxac6vD@xo7lcbvb7Tf7ilVZdNJCeD1O3kH9Uoj78mSd6qdWwwHH1g6v55z8k3rbRI1YN8JFWke/BtsyuBGAWATWKEjgsYwAg0o6Q2OS45CsLphweEaWbwRcpxHpiSJj3HitI4GrD7GGJiuELIfwi0yQ@yKJIjORksiZNGEHNofpht7E4w@kmR90fuBHmV52uKTfvw "C (gcc) – Try It Online")
[Answer]
# [Perl 5](https://www.perl.org/) `-pl`, 42 bytes
-1 byte, thanks to [@Abigail](https://codegolf.stackexchange.com/users/95135/abigail)!
```
s/(.)(a*)$/$1=~y!b-za!a-y!dr.$2=~y!a!z!r/e
```
[Try it online!](https://tio.run/##PYg7CoAwEAX7vcVCChWSoGDpYTb@EIIJiY1beHTXiODAPIYX5@R7kWwrU1fU1MqqdrhOdJoJSZ84JaO69yFkTHYWIRiBgQiIwZUtxcU1@AVcqQ/gH7hDPLawZ9HRPw "Perl 5 – Try It Online")
## Explanation
Mostly just using Regex here. First, match any character followed by a (greedy match of `0` or more) `a`s. In the replacement, return `$1`, `tr///`anslating (`y///`) chars to those directly preceding them (`/d`eleting any `a`s), followed by `$2`, translating `a`s to `z`s.
This should work for any length input.
[Answer]
# [Husk](https://github.com/barbuz/Husk), 14 bytes
```
→←xṁOmπ…'a'zΘN
```
[Try it online!](https://tio.run/##yygtzv6fm18enPqoqfH/o7ZJj9omVDzc2eife77hUcMy9UT1qnMz/P7//x@tlKiko5QMxFVAnAjiJIJYSWAWmF8FJtPzc9KUYgE "Husk – Try It Online") Uses a strategy similar to the one in [Kevin Cruijssen's answer](https://codegolf.stackexchange.com/a/206123).
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 33 bytes
```
≔⪪Ｓ¹θＷ›θ⟦a⟧«≔⊟θι←§β⊖⌕βι¿›ιa«↑θ≔υθ
```
[Try it online!](https://tio.run/##RY7BCoMwDIbP@hTFUwrdYdftJIwNYQdBdho7dBo10NVa6zYYPnvXobJADgl/vi9lK23ZSeV9OgzUaCiMIgeZNqMrnCXdABdsG7rn@/jVkkIGJ4vSoYVesGsikxvn7BNHCyDvDPQhTyEf5YHgYHfG2gmWukxX@Ia7YAcsLT5QO6zgSLr67YiHCjdU/w0kWBDM/BV2MfMz0Wocl3mKJ@@llH7zVF8 "Charcoal – Try It Online") Link is to verbose version of code. Vaguely based on @SurculoseSputum's answer. Explanation:
```
≔⪪Ｓ¹θ
```
Split the input into characters.
```
Ｗ›θ⟦a⟧«
```
Repeat until we only have `a` or nothing left.
```
≔⊟θι
```
Get the last remaining letter.
```
←§β⊖⌕βι
```
Print its cyclic decrement leftwards.
```
¿›ιa«
```
If there is no borrow, ...
```
↑θ
```
... print the remaining list in reverse, ...
```
≔υθ
```
... and clear the list to exit the loop.
]