[Question]
  [
To shuffle a string \$s\$, Alice applies the following algorithm:
* She takes the ASCII code of each character, e.g. `"GOLF"` → \$[ 71, 79, 76, 70 ]\$
* She sorts this list from lowest to highest: \$[ 70, 71, 76, 79 ]\$
* She reduces each value modulo the length of the string (4 in this case), leading to the list \$A = [ 2, 3, 0, 3 ]\$
* For each character at position \$n\$ (0-indexed) in the original string, she exchanges the \$n\$-th character with the \$A[n]\$-th character:
	+ exchange \$s[0]\$ with \$s[2]\$: `"GOLF"` is turned into `"LOGF"`
	+ exchange \$s[1]\$ with \$s[3]\$: `"LOGF"` is turned into `"LFGO"`
	+ exchange \$s[2]\$ with \$s[0]\$: `"LFGO"` is turned into `"GFLO"`
	+ exchange \$s[3]\$ with \$s[3]\$: this one doesn't change anything
She then sends the shuffled string `"GFLO"` to Bob.
## Task
Your task is to help Bob understand Alice's message by applying the reverse algorithm: given a shuffled string as input, output the original string.
The input string is guaranteed to contain only printable ASCII characters (codes 32 to 126).
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest answer wins.
## Test cases
**Input:**
```
AAA
GFLO
ron'llckR'o
Br b,!mn oGognooid
eAies a.turel vee.st hnrw .v
```
**Output:**
```
AAA
GOLF
Rock'n'roll
Good morning, Bob!
As we travel the universe...
```
  
[Answer]
# [MATL](https://github.com/lmendo/MATL), 19 bytes
```
tStn\Q!tfhP!"t@)@P(
```
[Try it online!](https://tio.run/##y00syfn/vyS4JC8mULEkLSNAUanEQdMhQOP/f/VUx8zUYoVEvZLSotQchbLUVL3iEoWMvKJyBb0ydQA "MATL – Try It Online") Or [verify all test cases](https://tio.run/##y00syfmf8L8kuCQvJlCxJC0jQFGpxEHTIUDjf6xLyH91R0dHdS51dzcffyBVlJ@nrp6Tk5wdpK6eD@Q7FSkk6Sjm5inku@en5@XnZ6YABVMdM1OLFRL1SkqLUnMUylJT9YpLFDLyisoV9MrUAQ).
### Explanation
The reverse algorithm is the same as the direct one just applying the swapping steps in reverse order.
```
t       % Input (implicit): string s of length N (row vector of chars of size 1×N)
S       % Sort (by ASCII codes)
tn      % Duplicate, number of elements: gives N
\       % Modulo (of ASCII codes), element-wise. Gives a 1×N numeric vector
Q       % Add 1 (because MATL uses 1-based indexing)
!       % Transpose into a column vector, of size N×1
tf      % Duplicate, find. Gives the N×1 column vector [1; 2; ...; N]
h       % Concatenate horizontally. Gives an N×2 matrix
P       % Flip vertically (for N=1 flips horizontally, but that still works)
!       % Transpose into a 2×N matrix 
!"      % For each column
  t     %   Duplicate the (partially processed) string: (*)
  @     %   Push current column: 2×1 vector of the form [s(k); k]: (**)
  )     %   Read elements (**) from string (*). Gives 2×1 char vector: (***)
  @P    %   Push current column, flip: gives [k; s(k)]: (****)
  (     %   Write (***) into (*) at positions (****)
        % End (implicit)
        % Display (implicit)
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 47 bytes
```
≔⪪Ｓ¹θＷ⌊⁻θυＦ№θι⊞υιＷυ«≔℅⊟υι≔§θιη§≔θι§θＬυ§≔θＬυη»↑θ
```
[Try it online!](https://tio.run/##bY@/DoIwEMZneYpza5M6uOqEDoZEIwnxARCQXlKuUFo1MT57BVFkcLjcn9933@UymZpMp8r7sG2xJJbUCi2LqHY2sQapZFzAsouGr4ObRFUAOyBh5ao@u5Y1AhznHC7awFY7sv0EOcSulcz15bjoODyC2efS0eRIqWKxrjvAB@EXhjaivLgPVgLkD02JgEm3L6i0srf6Kx7x4PYM4u47y1an@v2b9xsDZzGvCPROl6Q15oFfXNUL "Charcoal – Try It Online") Link is to verbose version of code. Explanation:
```
≔⪪Ｓ¹θ
```
Split the input string into characters.
```
Ｗ⌊⁻θυＦ№θι⊞υι
```
Sort them in ascending order.
```
Ｗυ«
```
Process the sorted characters.
```
≔℅⊟υι
```
Get the ASCII code of the next character in reverse order.
```
≔§θιη§≔θι§θＬυ§≔θＬυη
```
Swap the character at the current index with the character at that position (cyclically reduced modulo the length of the string).
```
»↑θ
```
Output the final character array vertically so it prints as a string.
[Answer]
# [J](http://jsoftware.com/), 34 32 31 bytes
```
<(C.>)/@,~i.@#;&~./@,.#|3 u:/:~
```
[Try it online!](https://tio.run/##RYnNCoJAGEX3PsUtoS/BPoN20w9Ogm6EwDcoG9OyGRh/2oSvbq5yceCee57jkqnAUYDgYwsxsWFEWRqPh3XEJy8I/aHi0N2vBp42u98dOhGIYfQcR@WlQQGSUtJfkji9zGaNJqrr/JURmfk@W9z8xVvDJOahjanuc1OyUg2u3HZW1eiV4qZFqe0H3JMz/gA "J – Try It Online")
Uses [Luis Mendo's insight](https://codegolf.stackexchange.com/a/239790/15469) "The reverse algorithm is the same as the direct one just applying the swapping steps in reverse order."
After that, we turn the problem into a single fold of all the swaps, using J's "Permute" verb `C.`, which can implement swaps directly. The only hiccup is that it doesn't allow self swaps, so we have to turn cases like `3 3 C. 'GOLF'` into `3 C. 'GOLF'`, which we do by call unique `&~.` while creating the swap pair.
[Answer]
# [R](https://www.r-project.org/), 104 bytes
```
function(s){i=sort(v<-utf8ToInt(s))%%(n=nchar(s))+1
for(j in n:1)v[rev(w)]=v[w<-c(j,i[j])]
intToUtf8(v)}
```
[Try it online!](https://tio.run/##RY2xCoMwEEB3vyIIwoVWwa0UM3TsbidxELlgRC5wuZxD6bdbO3V8b3iPj0xpyd5v6A6faZYQCZJ9B5ciC2hXZ/G3Pj5JTm2rCsjRvEz8o0tb@MiwmkCG7q3VgVFht6PTYe/qGdZrGNbRjkUg6ePrLIHaz/8JJT4CJjM1khk3o4hNErMQ76bR0hbHFw "R – Try It Online")
[Answer]
# Python3, 155 bytes:
```
def g(s,x,l):
 for i in range(l):h=s[(j:=(l-1-i))];s[j]=s[x[j]];s[x[j]]=h;
def f(s):
 s=[*s];g(s,[ord(i)%(t:=len(s))for i in sorted(s)],t);return''.join(s)
```
[Try it online!](https://tio.run/##VY0xT8MwFIT3/IpHJWQbpZEQC0rkIR3aBQmJNcpQyEvi1LwXPZtSfn1wGKoyne670938E0emp@dZlqXDHgYd8kvuTZlBzwIOHIEcaUCd2GhDo6fSar993Dpj2io0U5vgJclq/tSOVbZO9TqsM8E2D6Gt1uGGpdPO3OtYWo@UcnM9CSwRu4TaPJpKMH4JKVVM7NbeMoujqHut6rpWxmRXf9i/vN6CjTAp7z9Ob4o3t3wn8J7ffRLwgQdidt2/GGuHAY5F@kUPZ8QiRBhJvqE4p@LyCw)
[Answer]
# [Scala](http://www.scala-lang.org/), 101 92 bytes
```
s=>(s.sorted.map(_%s.size).zipWithIndex:\s){case((c,i),b)=>b.updated(c,b(i))updated(i,b(c))}
```
Saved 9 bytes thanks to @user.
Straightforward monadic-style implementation:
* `(s.sorted.map(_%s.size).zipWithIndex:\s)` creates the array "`A`" and traverses its elements (incl. corresponding index) from right to left via folding (`:\` = `foldRight`, accumulator initialized by input string `s`)
* `{case((c,i),b)=>b.updated(c,b(i))updated(i,b(c))}` updates the accumulator value `b` by swapping `b(i)` and `b(c)`. This part is quite verbose, since there is no `b.swap(c,i)` built-in.
[Try it online!](https://tio.run/##bVJha9swEP2eX3EVGbHA1Q8Ic8AtbRh0BNyNfSkM2T4nWhXJk2Q3NMtvz652bJMxfxC6d@8e757sC6nl2ea/sAjw3fhdU1UaAQ8BTekhrWs4zgBKrKAZukt4Dk6ZLSSr8Xb2ySrywlsXsBR7WUc/P1Gp3pGLd1X/UGH3xZR4WL54fiykxygqYsXjnCerXDR1KWmOoDxSnA@lorLg/HQGaKUmU3Jfa/SQwDP@jsgWAEvTlMHtqr/EPbZ@fNr04Hrz9DigzpqF1sVrtrB9M7PF68IsnNV64Nw5yOObvQG7tltjrSovOtaWsLfO0LIx3Nn8ZpjAVJEjKULjUEOLKHyAnXFvINqLMQ9vCMHJlghhhxSkatF5FEIwEuEzOirruqABokvKZTwlXnL4fDvu39GmXkovl0z1OM@Jd4LjB7mbqOmlgjZ9bgCeMXa5wp/5UVUQ/aOZXBlg95sse7j/xgC1R2APWbbJ2GmUGJhLuPrmAz4SJ1GI8FDTj0fyS5hP@H@psgiN1PxDfn5ldGTTQhS@U/VX6bbKdHgXwux0/gs "Scala – Try It Online")
[Answer]
# Python 3, 143 bytes
```
def u(i):
 m=len(i);p=list;i=p(i);a=[x%m for x in sorted(p(map(ord,i)))]
 for l in range(1-m,1):i[-l],i[a[-l]]=i[a[-l]],i[-l]
 return''.join(i)
```
I found it easiest to transform the input to a list and then back again, but I wouldn't be surprised if there is a more compact way to accomplish this.
[Try it online!](https://tio.run/##VY0xa8MwEIV3/4proEgCxRC6lAQN7pAsgUJX48GtL8mlkk6c5TT99a4daEmne@@7D176zieOT89JxrHDAwyazLqA4DzGKW6S89TnDbk0t9bV18cABxa4AkXoWTJ2OunQJs3SWTLGNMVN8LMgbTyiXi2DXZk11UvfWKrb@TbuN9gbL0AwDxKVKs9M8/aYhGLWg1ZVVSljir@@2@5f78FCOCrvPz7fFC/u@YvAu30IEXjHx8hM3b83VoQ9tOW0ix4uiGWf4RTlC8rLJI4/ "Python 3.8 (pre-release) – Try It Online")
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 30 bytes
```
:C₌sL:‹£%Ṙ(:¥n"İn¥"$Z÷→÷Ȧ←÷Ȧ&‹
```
[Try it Online!](https://vyxal.pythonanywhere.com/#WyIiLCIiLCI6Q+KCjHNMOuKAucKjJeG5mCg6wqVuXCLEsG7CpVwiJFrDt+KGksO3yKbihpDDt8imJuKAuSIsIiIsImVBaWVzIGEudHVyZWwgdmVlLnN0IGhucncgLnYiXQ==)
What a mess of 30 bytes. Probably gonna be outgolfed by better stack control.
## Explained
```
:C₌sL:‹£%Ṙ(:¥n"İn¥"$Z÷→÷Ȧ←÷Ȧ&‹
:                              # Push two copies of the input string
 C                             # and get the character code of each letter in the second copy
  ₌sL                          # push that sorted and it's length (parallel apply)
     :‹£                       # place the length of the string - 1 into the register - this will keep track of the nth character we're getting
        %Ṙ                     # reverse the list of each character code modulo the length of the string - this gets us our modulo indices (A[n])
          (                    # for each index n in that list:
           :                   #   The top of the stack is the first copy of the input string from earlier - we want to preserve this because we're modifying it with assignment, so make another copy to extract characters from
            ¥n"İ               #  that string's (register)th and nth character
                n¥"            #  push the list [n, register]
                   $Z          #  and then push zipped([n, register], [(register)th char, nth char]) - this allows us to create a list of [index to assign, character to assign]
                     ÷→        #  Place the last pair into the ghost variable for a bit, as we need to focus on the first pair of assignment.
                       ÷Ȧ      #  string[n] = (register)th char
                         ←÷Ȧ   #  string[register] = nth char
                            &‹ #  Increment the register to swap the next character position.
                               # After all that, the final string is implicitly printed.
```
[Answer]
# [Lua](https://www.lua.org/), ~~231~~ 220 bytes
```
s=...t={}s:gsub(".",load('table.insert(t,(...):byte())u=s.sub'))table.sort(t)for i=#t,1,-1 do a=t[i]%#t+1 i,j=math.min(a,i),math.max(a,i)s=u(s,1,i-1)..u(s,j,j)..u(s,i+1,j-1)..(i~=j and u(s,i,i)..u(s,j+1)or"")end print(s)
```
[Try it online!](https://tio.run/##LY5NasMwEIWvMjiEaLAyoG1Ai56jdCFjtRnhyEUzShtKe3VVcbJ7P9@Dt9TQmngiUv/zK6cPqZMZaLDLGmZz0DAtkThLLGrUms7habppNIjVC3X6gPigZL0z@L4WYL9T6@zRwbxC8PrKb/udjg7YJn8JeqYLZxMso3248L058dVIH/LRIdFdJ5ueikdn05Yb/vMJQp5hy/vuyY4O1zIMGHv1WTirEWytxReOAoG0lrjANfarCudcvoCu/w "Lua – Try It Online")
[Answer]
# [Brachylog](https://github.com/JCumin/Brachylog), 82 bytes
```
lL∧L⟦₅R⁰∧?oạ%ᵐ↙L;R⁰z↔I∧?g,I↰ˡ↙1c
g;R⁰z{[[X,[A,B]],R]∧(A R∧X∋↙B.∨B R∧X∋↙A.∨X∋↙R.)}ᵐ
```
[Try it online!](https://tio.run/##SypKTM6ozMlPN/r/P8fnUcdyn0fzlz1qag161LgByLPPf7hroerDrRMetc30sQYJVj1qm@IJkknX8XzUtuH0QqCMYTJXOkSyOjo6QifaUccpNlYnKBaoTMNRIQhIRTzq6AYqdNJ71LHCCVnEESQCZQfpadYCrfr/X8mpSCFJRzE3TyHfPT89Lz8/M0XpfxQA "Brachylog – Try It Online")
I couldn't find any reasonable way to swap 2 elements by index in Brachylog, so the second line is a verbose and ugly implementation of that.
Since Brachylog is prolog based, I could have applied the transform forwards and let it calculate the inverse automatically, but it was easier to just reverse the list.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), 16 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
Ç{Dg%ā<øRvDyèyRǝ
```
[Try it online](https://tio.run/##yy9OTMpM/f//cHu1S7rqkUabwzuCylwqD6@oDDo@9/9/dzcffwA) or [verify all test cases](https://tio.run/##yy9OTMpM/V9TVmmvpPCobZKCkn2ly//D7dUu6apHGm0O7wgqc6k8vKIy6Pjc/7U6/x0dHbnc3Xz8uYry89RzcpKzg9TzuZyKFJJ0FHPzFPLd89Pz8vMzU7hSHTNTixUS9UpKi1JzFMpSU/WKSxQy8orKFfTKAA).
The shuffle method described in the challenge description would be this:
```
Ç{Dg%ā<øvDyèyRǝ
```
[Try it online](https://tio.run/##yy9OTMpM/f//cHu1S7rqkUabwzvKXCoPr6gMOj73/393fx83AA) or [verify all test cases](https://tio.run/##yy9OTMpM/V9TVmmvpPCobZKCkn2ly//D7dUu6apHGm0O7yhzqTy8ojLo@Nz/tTr/HR0dudz9fdy4gvKTs9Xz1Ivyc3K43PPzUxRy84vyMvPSdRSc8pMUuRyLFcpTFUqKEstScxRKMlIVSvMyy1KLilP19PQA).
And the top program simply reverses the list of indices to unshuffle.
We can add a trailing `=` after the programs above to see the intermediate steps: [try it online](https://tio.run/##yy9OTMpM/f//cHu1S7rqkUabwzvKXCoPr6gMOj7XlqvW5dA2ey4kuSCE5P//7v4@bgA).
**Explanation:**
```
Ç          # Convert the (implicit) input to a list of codepoint-integers
 {         # Sort them from lowest to highest
  Dg       # Duplicate, pop and push the length
    %      # Modulo the codepoints by this length
     ā     # Push a list in the range [1,length] (without popping)
      <    # Decrease each by 1 to make the range [0,length)
       ø   # Create pairs of the two lists
        R  # Reverse this list of pairs
v          # Loop over each pair of indices `y` of this list:
 D         #  Duplicate the current string
           #  (which is the implicit input in the first iteration)
  yè       #  Pop one string, and get the character-pair at indices `y`
    yRǝ    #  Insert them at back in the string at the reversed indices-pair `y`
           # (after the loop, the resulting string is output implicitly)
```
The swapping portion is taken from [my answer here](https://codegolf.stackexchange.com/a/236367/52210).
[Answer]
# [Ruby](https://www.ruby-lang.org/), 70 bytes
```
->s{r=0;s.bytes.sort.reverse.map{|c|s[c],s[r]=s[r-=1],s[c%=s.size]};s}
```
[Try it online!](https://tio.run/##KypNqvyfZvtf1664usjWwLpYL6myJLVYrzi/qESvKLUstag4VS83saC6JrmmODo5Vqc4uijWFkjo2hqCOMmqtkDFmVWpsbXWxbX/CxTSopWK8vPUc3KSs4PU85Vi/wMA "Ruby – Try It Online")
[Answer]
# [K (ngn/k)](https://codeberg.org/ngn/k), ~~36~~ 34 bytes
```
{x{x[y]:x@|y;x}/|+(!#x;(#x)!x@<x)}
```
[Try it online!](https://ngn.codeberg.page/k#eJx9kEGLwjAQhe/zK1JdqLLawnrY3WYP1oOyIAhei2CtSVsaM26S1hR1f/um60UQvEyYmczjfY9HZ3u2SbuJ7PTSUnsNL68Dr2/poG+Hnp1+2eEVwETnl6T9VREnhFi6xYoOtjwtBbW0pWq4uYJJenEc9+h/3XTtYr5cuX6xWs5vA4XSFyKr1j66+Rqzype+QiFu65kiu5F3kAQXmEvEct9dI+7JAZUsZT4iM9x5t88sLpkmaWBqxQRpGAu0IYVUJxI0nQlNTowYlTZuawpGalk2TGkWBIETAAihMOaoozDMcM9yFNwJpFnFbFakMmdBhofwp2balCh1+Db5fP+YhJoJPq6lLmrOhXM01ka5RwN8y2NtIgBHDx043MHCIxk88w+wqs2dnAsQ7tKCx0zgGS/AH1Xwm4k=)
As with the other answers, applies the swaps in the opposite order.
* `(...;(#x)!x@<x)` mod the sorted ASCII character codes by the length of the input
* `(!#x;...)` generate indices from 0..len(input)
* `|+` transpose this pair of lists into a list of pairs, then reverse its order
* `x{...}/` set up a fold, seeded with `x` (the original input), and this list of pairs indicating the order of the swaps
	+ `{x[y]:x@|y;x}` swap the pair of elements of this current iteration, returning the modified list
]