[Question]
  [
*We seem to [never](https://codegolf.stackexchange.com/questions/89283/print-an-alphabet-wave/89306#comment217718_89283) get [tired](https://codegolf.stackexchange.com/questions/89283/print-an-alphabet-wave/89306#comment217928_89283) of alphabet-related challenges...*
---
# The recipe
Given
* a string of letters `S`, and
* two positive integers `M`, `N`,
produce an alphabet soup with the letters of `S` occupying **random positions** in a **rectangular bowl** of size `M`×`N`, **framed** by a non-alphabetic, non-space character to represent the rim of the bowl.
Positions not used by letters should be displayed as spaces. See the **examples below**.
# Aditional rules
* The size `M`×`N` refers to the **interior** of the bowl. The size including the rim is `M+2`×`N+2`.
* Each character from `S` should appear *once* in the bowl, in a **different position**; that is, one character cannot overwrite another.
* `S` **may contain duplicates**. For instance, if `S` is the string `'abcc'`, the soup must contain one `a`, one `b`, and two `c` (all in different positions).
* The inputs will satisfy the **restrictions** `M >= 1`, `N >= 1`, `1 <= length(S) <= M*N`.
* The rim of the bowl can be **any non-alphabetic, non-space character**, consistent across program runs and input values.
* Letter positions in the bowl are random, so the result may differ every time the program is run with the same inputs.
* Given the input, every possible set of letter positions should have a **non-zero probability**. Since this cannot be checked from a few realizations of the program, please explain how your code fulfills this.
* Leading or trailing **whitespace** around the rim is allowed.
* `S` will contain are **only uppercase** letters. If wou wish, you can choose to take **only lowercase** letters.
* Input and output are [flexible](https://codegolf.meta.stackexchange.com/q/2447/36398) as usual. For example, the output can be a string with newlines, a 2D character array, or a list of lines.
* [Programs or functions](http://meta.codegolf.stackexchange.com/a/2422/36398) are allowed, in any [programming language](https://codegolf.meta.stackexchange.com/questions/2028/what-are-programming-languages/2073#2073). [Standard loopholes](https://codegolf.meta.stackexchange.com/questions/1061/loopholes-that-are-forbidden-by-default) are forbidden.
* The shortest code in bytes wins.
# Examples
Inputs are shown as `S, [M N]`, where `M` is number of rows and `N` is number of columns. The character `#` is used for the rim.
```
'O', [1 1]:
###
#O#
###
'HEY', [1 3]:
#####
#YHE#
#####
'HELLO', [4 11]:
#############
#  O        #
#         H #
#    LE     #
#   L       #
#############
'ADVNJSGHETILMVXERTYIOJKCVNCSF', [8 12]:
##############
#K  V  L   S #
# A   V  X H #
#T    M C    #
# I       O N#
#  YC        #
# G  I   R SE#
#   J      F #
#JT  D  V EN #
##############
'OOOOOOOOOOXXXXX', [13 31]:
#################################
#    X                          #
#                O              #
#                               #
#                  X            #
#                        O      #
#             X           O     #
#      O                        #
#         X                     #
#                        O      #
#       X                       #
#                    O          #
#  O      O      O              #
#                             O #
#################################
'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ', [11 41]
###########################################
#                                       JU#
#     Q         C M    G     R T U Y  H   #
#  KI          E   H    M   YO            #
#      V BW        I    JC                #
#     SV           D     P   B          U #
#           A     F    RF   J  KP E       #
#            E   N      TH        Z       #
#    N  BM  O     Q   I        AS N  WX   #
#   S     O  K       G L       P       Q  #
#Z     L T         R   L       A      F DD#
#      V   Y           WX   C       G XZ  #
###########################################
```
  
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~20~~ ~~18~~ ~~16~~ ~~15~~ 14 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
*j.rS²ô2Føε8.ø
```
Takes three inputs in the order: height, width, string. Output as a 2D list of characters.  
Uses `8` as border, but could be any digit.
-1 byte thanks to *@Grimy*.
[Try it online](https://tio.run/##AUMAvP9vc2FiaWX//ypqLnJTwrLDtDJGw7jOtTguw7j/XUrCu/84CjEyCkFEVk5KU0dIRVRJTE1WWEVSVFlJT0pLQ1ZOQ1NG) or [verify all test cases](https://tio.run/##yy9OTMpM/W/m5unpeWjlf60svaLgQ@sObzFyO7zj3FYLvcM7/tfWeh3arXNom/1/fy5DIPRwjQSSxkDax8efy4TL0JDL0SXMzyvY3cM1xNPHNyzCNSgk0tPfy9s5zM852I3LgsvQiMsfDiJAgMvQmMsYqNHJ2cXVzd3D08vbx9fPPyAwKDgkNCw8IjKKHBmQU0wMAQ). (TIO contains `}}J»` in the footer to pretty-print the result; feel free to remove it to see the actual output 2D list of characters instead.)
**Explanation:**
```
*               # Multiply the (implicit) width and height inputs
 j              # Pad the (implicit) input-string with up to that amount of leading spaces,
                # so the total string-length is equal to that value
  .r            # Shuffle the characters in the string
    S           # Convert the string to a list of characters
                # (edge-case for the zip below with strings of size 1 with 1x1 dimensions)
     ²          # Push the width input again
      ô         # Split the list of characters into parts of that size
       2F       # Loop 2 times:
         ø      #  Zip/transpose the 2D list; swapping rows/columns
          ε     #  Inner map over each line:
           8.ø  #   And surround this line-list with a leading/trailing "8"
                # (after the loop, the result is output implicitly)
```
[Answer]
# [APL (Dyalog Unicode)](https://www.dyalog.com/), 25 [bytes](https://codegolf.meta.stackexchange.com/a/9429/43319 "When can APL characters be counted as 1 byte each?")[SBCS](https://github.com/abrudz/SBCS ".dyalog files using a single byte character set")
```
'#',∘⌽∘⍉⍣4{⍵⍴⊃¨↓∘⍺¨?⍨×/⍵}
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT///X11ZXedRx4xHPXtBZG/no97FJtWPerc@6t3yqKv50IpHbZPBErsOrbB/1Lvi8HR9oGTt/7RHbRMe9fY96pvq6Q9St974UdtEIC84yBlIhnh4Bv8H0kBF6o4uYX5ewe4eriGePr5hEa5BIZGe/l7ezmF@zsFu6gppChYKhkYA "APL (Dyalog Unicode) – Try It Online")
-22 thanks to @ngn, -7 thanks to @ngn and @Adám
Explanation:
```
'#',∘⌽∘⍉⍣4{⍵⍴⊃¨↓∘⍺¨?⍨×/⍵}
          {            ⍵} ⍝ Function that generates the content
                          ⍝  argument: ⍵ (width and height), ⍺ (string)
                     ×/   ⍝ get the product
                   ?⍨     ⍝ For each randomized elements
               ↓∘⍺¨       ⍝ take the character in ⍺
           ⍵⍴⊃¨           ⍝ turn it back into a matrix of shape ⍵
    ∘ ∘ ⍣4                ⍝ Then, 4 times, do these 3 things:
'#',                      ⍝ - prepend a # to the axis
     ⌽                    ⍝ - reverse the columns
       ⍉                  ⍝ - swap columns and lines
```
# ~~[APL (Dyalog Extended)](https://github.com/abrudz/dyalog-apl-extended), 21 [bytes](https://codegolf.meta.stackexchange.com/a/9429/43319 "When can APL characters be counted as 1 byte each?")[SBCS](https://github.com/abrudz/SBCS ".dyalog files using a single byte character set")~~
**The rim's angles are different characters**
```
{⌂disp⊂⍵⍴⊃¨↓∘⍺¨?⍨×/⍵}
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT9dNrShJzUtJTfn/qG9qsKteqLOvi3pSfoVCfp76o67FGkBRv@BHvWs09TRS8xKTclKDHX1CgBJAcedI9eLEnBJ1zf/Vj3qaUjKLCx51NT3q3fqod8ujruZDKx61TX7UMeNR765DK@wf9a44PF0fKFn7P@1R24RHvX1AAzz9QerWGz9qmwiyPMgZSIZ4eAaDnAJUpO7oEubnFezu4Rri6eMbFuEaFBLp6e/l7Rzm5xzspq6QpmChYGgEAA "APL (Dyalog Extended) – Try It Online")
Using the dfn to display the box.
[Answer]
# [Python 3](https://docs.python.org/3/), 110 bytes
```
lambda s,m,n,r=['#']:[r+(n*r+[i for i,j in{*zip(s+m*n*' ',range(m*n))}]+n*r)[k*n:-~k*n]+r for k in range(m+2)]
```
[Try it online!](https://tio.run/##nY1NT4NAGITv/RWbeFgWXg@UHkyTHpTSAqVFC2IrErMK2LWwJUsv1ehfx8VvOTqHTXZmnneqw36z40aTj26agpZ3KUU1lMBBjGJ8hJNhLDSFq0KLGcp3AjF4RIw/q0@sUmqtVLmKEQZB@UOmyB8hL4km6yTeqnx4/CrfRBPv5FZy6LOo9UnSpFmOUlZXBT0o9xsqbqkQ9ECGPSTVEgXjWQv9hB9Zq0owvlfUtgKozqoRxqTX@zqXK9jHoINOyG/Pttata3Rdz5PtAeid@uk4WrjB1LZCx5tHK2sZrh3fnZnRwgwmGE5A7/8F/G@tWsktA4zu0TNzbE2mtuPOvPnCP79YBuFldLVaX/8nkRM6DORE8wY "Python 3 – Try It Online")
Randomizes by using a `set` comprehension and returns a 2D character array.
[Answer]
# Bash + coreutils, ~~139~~ 125 characters
```
r=`printf %$3s@@|tr \  @`
echo $r
printf %$[$2*$3]s $1|fold -1|shuf|tr -d \\n|fold -$3|paste -d@ <(:) - <(:)|head -$2
echo $r
```
Sample run:
```
bash-5.0$ bash soup.sh HELLO 4 11
@@@@@@@@@@@@@
@  H        @
@      OE   @
@    L      @
@          L@
@@@@@@@@@@@@@
```
[Try it online!](https://tio.run/##S0oszvj/v8g2oaAoM68kTUFVxbjYwaGmpEghRkHBIYErNTkjX0GliAsuHa1ipKViHFusoGJYk5afk6Kga1hTnFGaBtKim6IQE5MHFVYxrilILC5JBYo6KNhoWGkq6IKpmozURJC0Eczs////Ozo5u7i6uXt4enn7@Pr5BwQGBYeEhoVHREaRI/Pf0PC/iSEA "Bash – Try It Online")
### Bash + coreutils + boxes, 97 characters
```
printf %$[$2*$3]s $1|fold -1|shuf|tr -d \\n|fold -$3|boxes -dsimple -s$[$3+2]x$[$2+2] -pa0 -itext
```
Sample run:
```
bash-5.0$ set -- HELLO 4 11
bash-5.0$ printf %$[$2*$3]s $1|fold -1|shuf|tr -d \\n|fold -$3|boxes -dsimple -s$[$3+2]x$[$2+2] -pa0 -itext
*************
* O   L  E  *
*      H    *
*           *
*     L     *
*************
```
[Try it online!](https://tio.run/##S0oszviflF@RWqyhqVCtkJxYYq1Q@7@gKDOvJE1BVSVaxUhLxTi2WEHFsCYtPydFQdewpjijNK2mpEhBN0UhJiYPKqxiXAM2BShanJlbkJOqoFsM1G2sbRRbATIFSCvoFiQaKOhmlqRWlPz//9/RydnF1c3dw9PL28fXzz8gMCg4JDQsPCIyihyZ/4aG/00MAQ "Bash – Try It Online") (Partially, as `boxes` is not installed on TIO.)
[Answer]
# [J](http://jsoftware.com/), ~~30~~ 29 bytes
-1 byte thanks to Jonah
```
'#'|.@|:@,^:4[$*/@[(?~@[{{.)]
```
[Try it online!](https://tio.run/##nY7BCoJQEEX3fcVYwVSY9VIiH0SaaWovLTXTpDaRRJs@wOjXTTOCXHaHWcw9d4a55TJHyXHMURmx0RQwhSkFBB6GQIvuC6B5zMixhQ9BeVCFP1EpafcGStKZPZUky4TuMe82LufrHUhRKaCLUM3FxY8vlr6px/gLRJAqwJhbQxMgo5Kpi9Cx/aWpBxZbh5HuBbHl2istdDTfqO0QEcTqg6@iUvUYAekdU@faQjeWpmWv2NpxN1vPD3bhPooP/xDMXw "J – Try It Online")
[Answer]
# [PowerShell](https://github.com/TryItOnline/TioSetup/wiki/Powershell), ~~163~~ ~~111~~ 93 bytes
```
param($w,$h,$s)'#'*$w+-join($s|% *ht($w*$h)|% t*y|sort{Random})+'#'*$w-replace".{$w}",'#$0#
'
```
[Try it online!](https://tio.run/##K8gvTy0qzkjNyfn/vyCxKDFXQ6VcRyVDR6VYU11ZXUulXFs3Kz8zT0OluEZVQSujBCitpZKhCeSUaFXWFOcXlVQHJeal5OfWampDNOgWpRbkJCanKulVq5TXKumoK6sYKHOp////38Twv6Hhf3VHJ2cXVzd3D08vbx9fP/@AwKDgkNCw8IjIKHJk1AE "PowerShell – Try It Online")
Takes input as `$w`idth, `$h`eight, `$s`tring.
Constructs a string of `#` of the appropriate `$w`idth, string-joins that with some computation, and then that same `#` string again. The computation starts with taking the input `$s`tring, and doing a .padRig`ht` up to the `$w`idth by `$h`eight length (i.e., make a string long enough to completely take up the rectangular space. We then convert that string `t`oCharArra`y`, and `sort` it `Random`ly. That gives us the mixed-up middle portion. Finally, we `-replace` it into chunks of equal `$w`idth, and surround those chunks with `#`s.
*-52 thanks to inspiration from AZTECCO*  
*-18 bytes thanks to mazzy*
[Answer]
# JavaScript (ES7), 125 bytes
Returns a string. Uses `0` as the frame character.
```
(s,h,w)=>(a=[...s.padEnd(w++*h++)].sort(_=>Math.random()-.5),g=x=>y+~h?(x%w&&y%h&&a.pop())+[`
`[x-w]]+g(x<w?x+1:!++y):a)(y=0)
```
[Try it online!](https://tio.run/##bctNT8JAFIXhPb9CF5R7ve1E/EgMcUoMVgELJEIaSdPIhEJHg52m0zDTjX@91rgzJGf3nudTHIXelh9F5eUq3TV73oB2pWuQ@yB4zBjTrBBpkKdgiC4kESZMq7KCd@7PRCVZKfJUfQF67BbdjFvu1/Qth2C7xnHqrnQcwQpVACLFm84mtp5JEsrA3puhpf7gnKjGgUCo@SU2W5Vrddixg8pgD71Fzz3rt0Ps/CvjYP3Xrk@1MPyVN@3hBH14jObT5fM4WE3CWfQWvK7Wk8X0ZRTNR8unlt217Aqx@QE "JavaScript (Node.js) – Try It Online")
### Commented
```
(s, h, w) => (               // s = string; h = height; w = width
  a =                        // build an array a[] consisting of:
    [...s.padEnd(w++ * h++)] //   all original characters in s padded with spaces for a
    .sort(_ =>               //   total length of w * h, in a random order
      Math.random() - .5     //   (this is not guaranteed to be uniform, but it is not
    ),                       //   required to be)
  g = x =>                   // g is a recursive function taking x:
    y + ~h ?                 //   if we haven't reached the end of the grid:
      ( x % w &&             //     if we're not located on a vertical border
        y % h &&             //     nor on a horizontal border,
        a.pop()              //     extract the last character from a[]
      ) +                    //     (otherwise, append '0')
      [`\n`[x - w]] +        //     if we've reached the end of the row, append a linefeed
      g(                     //     append the result of a recursive call:
        x < w ? x + 1 : !++y //       using either (x+1, y) or (0, y+1)
      )                      //     end of recursive call
    :                        //   else (end of grid):
      a                      //     a[] is now empty and can be used as an empty string
)(y = 0)                     // initial call to g with x = y = 0
```
[Answer]
# [APL (Dyalog Extended)](https://github.com/abrudz/dyalog-apl-extended), 23 [bytes](https://codegolf.meta.stackexchange.com/a/9429/43319 "When can APL characters be counted as 1 byte each?")[SBCS](https://github.com/abrudz/SBCS ".dyalog files using a single byte character set")
Anonymous tacit infix function. Takes `[M,N]` as left argument and `S` as right argument.
```
'#',∘⌽∘⍉⍣4⊣⍴×/⍛(?⍨⍤⊣⊇↑)
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT9dNrShJzUtJTfn/X11ZXedRx4xHPXtBZG/no97FJo@6Fj/q3XJ4uv6j3tka9o96VzzqXQIS62p/1DZR83/ao7YJj3r7HvVN9fR/1NV8aL0xUBjICw5yBpIhHp7B/w0VDBXSFNT91bkMFYxBLA/XSHUuEwVDQwjHxwcoZaFgaATiOrqE@XkFu3u4hnj6@IZFuAaFRHr6e3k7h/k5B7sBTTBWMIaYBgcRIACUMVQwAcs4Ojm7uLq5e3h6efv4@vkHBAYFh4SGhUdERpEjow4A "APL (Dyalog Extended) – Try It Online")
`×/⍛(`…`)` apply the following function between the arguments, replacing the left argument with its product:
 `↑` take `M`×`N` characters from `S`, padding with spaces on the right
 `⊇` reorder that to the following order: 
 `?⍨⍤` the shuffled indices 1 through…  
 `⊣` the left argument (`M`×`N`)
`⍴` **r**eshape that to the following shape:
`⊣` the left argument (i.e. `M` rows and `N` columns)
`'#'`…`⍣4` apply the following function four times, each time with the hash character as left argument:  
 `∘⍉` transpose the right argument  
 `∘⌽` mirror the right argument  
 `,` concatenate a column of hashes to the left side of that
[Answer]
# PHP 7.4, ~~107~~ ~~99~~ 94 characters
```
fn($s,$r,$c)=>_.chunk_split(($b=str_pad(_,$c,_)).str_shuffle(str_pad($s,$r*$c)),$c,"_
_").$b._
```
Thanks to:
* [Ismael Miguel](https://codegolf.stackexchange.com/users/14732/ismael-miguel) for reminding me about PHP 7.4's arrow functions (-10 characters)
* [Night2](https://codegolf.stackexchange.com/users/81663/night2) for 
efficiently reversing the concatenations and the `join()` (-8 characters)
* [Night2](https://codegolf.stackexchange.com/users/81663/night2) for showing how to use `chunk_split()`'s `$end` parameter (-5 characters)
[Try it online!](https://tio.run/##nY9Rb4IwFIXf@ysIaWJrGpJNH0wUzYYoIIIKMjAmzWSSLhpsrPx@bDUz84EXb/rU851z7uWM14MRZxwAKE4V18y6KBEUBJ4JzLE5pEbOqvJABT/@XhCCO1NczpR//yAqAUIxNtSHYFVRHPfoT7wltGUCVpROAdWxAXcGrfsA7HN20m51qBW2iPYmHyaavi23pd5/kh07uwOdRsD3VUZXUk0hH@Mk8KKpY8euP09SexVnbujNrCSwoon09qT3vcEbPiZVo5bpyG0aqz6tsT2ZOq438@dBuFiuonidfKXZ5hVFtcnbu//a6is "PHP – Try It Online")
### PHP 7.3, ~~117~~ ~~112~~ 108 characters
```
function s($s,$r,$c){echo _.chunk_split(($b=str_pad(_,$c,_)).str_shuffle(str_pad($s,$r*$c)),$c,"_
_").$b._;}
```
Thanks to:
* [Night2](https://codegolf.stackexchange.com/users/81663/night2) for efficiently reversing the concatenations and the `join()` (-5 characters)
* [Night2](https://codegolf.stackexchange.com/users/81663/night2) for showing how to use `chunk_split()`'s `$end` parameter (-4 characters)
Sample run:
```
php > function s($s,$r,$c){echo _.chunk_split(($b=str_pad(_,$c,_)).str_shuffle(str_pad($s,$r*$c)),$c,"_
php " _").$b._;}
php > s('HELLO', 4, 11);
_____________
_  L        _
_        L  _
_E          _
_    OH     _
_____________
```
[Try it online!](https://tio.run/##K8go@G9jXwAk00rzkksy8/MUijVUinVUinRUkjWrU5Mz8hXi9ZIzSvOy44sLcjJLNDRUkmyLS4riCxJTNOKBinTiNTX1QALFGaVpaTmpGjBJsClaQFM0QaqU4rnilTT1VJL04q1r/xdrqDs6Obu4url7eHp5@/j6@QcEBgWHhIaFR0RGkSOjrqNgaKijYGKoaf0fAA "PHP – Try It Online")
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~22~~ 19 bytes
```
tZ"ibpyn&Z@(TT35&Ya
```
[Try it online!](https://tio.run/##y00syfn/vyRKKTOpoDJPLcpBIyTE2FQtMvH//2gTBdNYLvXEpOSUVHUA "MATL – Try It Online")
Thanks @LuisMendo for saving 3 bytes, so now it has the same bytecount as @flawr's [answer](https://codegolf.stackexchange.com/a/193908/32352), but sufficiently different to post anyway. High-level agorithm overview:
```
 Z"                  % Create n x m matrix of spaces
           (         % Index into this matrix:
   i                 %  The alphabet vermicelli (explicit input)
        &Z@          %  at a random locations (randperm), which are
      yn             %   length(S) numbers, ranging
t   bp               %   from 1 to n*m
            TT35&Ya  % And finally add a border
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), 121 bytes
Creates the bowl, queries the indices of all spaces within the bowl, samples a number of spaces equal to the size of the string, and fills them in. `sample` does not return a sorted list, so there is no need to shuffle. Searching indices up to `9*m*n` (which almost certainly goes out of range) will still get all spaces and is 1 byte shorter than `r.size`.
```
->s,m,n{r=[t=?@*(n+2),*["@#{' '*n}@"]*m,t]*$/;i=-1;(0..9*m*n).select{|j|r[j]==' '}.sample(s.size).map{|j|r[j]=s[i+=1]};r}
```
[Try it online!](https://tio.run/##KypNqvyfZvtf165YJ1cnr7rINrrE1t5BSyNP20hTRytayUG5Wl1BXSuv1kEpVitXpyRWS0XfOtNW19Baw0BPz1IrVytPU684NSc1uaS6JqumKDor1tYWqKNWrzgxtyAnVaNYrzizKlVTLzexAK6gODpT29Ywtta6qPZ/QWlJsUJatLq/uo6CIRDFcsFEPFwjIWLGyGI@PiCVJkAJJKWOLmF@XsHuHq4hnj6@YRGuQSGRnv5e3s5hfs7BbkDlFkDlRkjKnZxdXN3cPTy9vH18/fwDAoOCQ0LDwiMio8iRATkS6EoTw9j/AA "Ruby – Try It Online")
[Answer]
# [Red](http://www.red-lang.org), ~~120~~ ~~116~~ ~~114~~ 112 bytes
-2 bytes thanks to @Kevin Cruijssen! 
```
func[s m n][random pad s m * n insert/dup t: copy"00"0 n
print t loop m[print rejoin[0 take/part s n 0]]print t]
```
[Try it online!](https://tio.run/##nY/BToNAGITP8BSTPXopSA@mN21pgVJQWhHc7GFll1i1u2ShMT49hWJ8AOc0/z@TLxkjRZ9JQZltuBL6NGulFFD6264X6OuzqmiLExSjU46GC4yfGygcVStNNxPnBt0ClW5@iOMQB8puzFF16PCldYMTnU4jP/RRUQcd/5SzhptuICk4jP3WWV9rI3n1DsrxhopRkhK4cG3LIoFfjt6bfBwPyRzuNbpf5Um03wT@IYx3eeFnhzJMo@0yT5b7NcEd3Nuxlv6pGDXQPHgT4GG58tebIIy28S5JH5@y/eE5fynK1/8kA9jF3GW2RWtch2AaSAjrLw "Red – Try It Online")
[Answer]
# [Perl 6](https://github.com/nxadm/rakudo-pkg), ~~74~~ 67 bytes
*-5 bytes thanks to Jo King*
```
{0 X~0 x$^n,|comb($n,[~] $^s.comb[pick *,^$^m*$n]X//' '),0 x$n X~0}
```
[Try it online!](https://tio.run/##K0gtyjH7n1upoJamYPu/2kAhos5AoUIlLk@nJjk/N0lDJU8nui5WQSWuWA/Ejy7ITM5W0NKJU4nL1VLJi43Q11dXUNfUAenJA@mt/V@cWKmQpmGio2BoqKOg7uHq4@OvrqmXlZ@Zp6EUk6ekaf0fAA "Perl 6 – Try It Online")
### Explanation
```
{                                                                 }
                                         ^$^m*$n  # Range 0 .. M*N-1
                                  pick *,  # Shuffle
                         $^s.comb  # Split S into chars
                                 [              ]  # Pick shuffled elements
                                                 X//' '  # undef to space
                     [~]  # Join
             # Split into n-character strings
             comb($n,                                  )
            |  # Flatten
     # Add top and bottom of bowl
     0 x$^n,                                            ,0 x$n
 # Add left and right of bowl
 0 X~                                                          X~0
```
[Answer]
# T-SQL 2017, 232 bytes
Testing this online is an older version of sql-server costing another character. I posted the shorter version.
**Golfed:**
```
DECLARE @ varchar(max)=''SELECT top 999 @+=substring(@i,number+1,1)FROM spt_values
WHERE type='P'and number<@a*@b
ORDER BY newid()WHILE-@b<1SELECT @=stuff(@+' ',@b*@a+1,0,'#
#'),@b-=1PRINT stuff(replicate('#',2+2*@a),2+@a,0,trim(@))
```
**[Try it online](https://data.stackexchange.com/stackoverflow/query/1120256)**
**Ungolfed:**
```
DECLARE @ varchar(max)=''
SELECT top 999 @+=substring(@i,number+1,1)
FROM spt_values
WHERE type='P'and number<@a*@b
ORDER BY newid()
WHILE-@b<1
SELECT @=stuff(@+' ',@b*@a+1,0,'#
#'),@b-=1
PRINT stuff(replicate('#',2+2*@a),2+@a,0,trim(@))
```
[Answer]
# [Perl 5](https://www.perl.org/) `-lF`, ~~99~~ 97 bytes
*-2 bytes courtesy of @NahuelFouilleul*
```
%k=map{$_=>$F[$_]||$"}0..($m=<>)*($n=<>)-1;say+($p='#'x($n+1)),map"#
#"x!($i++%$n).$_,values%k,$p
```
[Try it online!](https://tio.run/##FcvBDoIgHIDxO28R/J0QyqDmqfDorSdojVF5cCKyqGbLXj2y07f9ti@0N1ellPV6sOENRtfQHMGc5hnwRwpBYdD7mq0p@H9LtYv2xSkEnZN8WpQrxorlxQQRPK0odJxn4JkAUzyte7Qx6wsIKdnz5Yq2aPMdw70bfUzloRJSyVS65gc "Perl 5 – Try It Online")
[Answer]
# k4, ~~32~~ 28 bytes
```
{4{|+x,'"#"}/y#a?(a:-*/y)$x}
```
edit: -4 thanks to Galen Ivanov!
called like
```
f["hey";3 3]
```
---
explanation:
```
                 (a:-*/y)    / neg product of y and assign to a 
                         $x  / left pad x so we have char vector the length of the inner area
               a?            / take `a` random drawings. if a is negative, draw with no duplicates/replacements
             y#              / reshape to y's dimensions
 4{        }/                / do {} 4 times 
   |+x,'"#"                  / append "#" along right-side of x then transpose (+) and reverse (|)
```
[Answer]
# [Java (JDK)](http://jdk.java.net/), ~~180~~ 178 bytes
Not a single extra import:
```
(y,m,n)->{for(m*=n;y.length()<m;y+=" ");var s="";for(;m-->0;y=s)for(var c:y.split(s=""))s=Math.random()<.5?s+c:c+s;s="#".repeat(n);return(s+y+s).replaceAll(".{"+n+"}","\n#$0#");}
```
[Try it online!](https://tio.run/##zVNdb9owFH1OfsWV2YNNTAoVlSrcsDFGv0ZbqVTVpm0PbgiQznEi22kVIX47syGMautDH/awJ1/fc3xz78m5j/yJtx6nP9dpVuTKwKO9h6VJRdhk/l@5WSljk@byVVAblfDsT4g/G5fyP5zWb7m4kCZRMx4nfrqL4E6lO8LJgMJHCkMKt31Y@t4t8KIQFR4AtwA8WAhiwvyVHwuuNVzxVDpeUT6INAZtuLHHU55OIbMQnhiVyvm3H8DVXBPH9F5@bQtTcF3NE/Ui2CJ9MFs2RN4aVzSjkrT6y1mucNaMJKtCkci5WWBykrEqiBAgwp64Ah0hxByNZa1Wv82qSBN3dVjcq0JdiNRgxyJER1fcLELF5TTPbKXw6L0O4l4caGYJDRSqpEi4wZIwlZhSSayDKtDE5YXVbyAERuESBTJAK0TRd9l4127YRlZrz2N24kmlTZKFeWnCwk5lhMT1WOFWXVRKvShnM5FMrYRucEShS@GIkLe9byPaoZ23ss9H4/ENol3aefOTwaf768vJ2fno7mJ8df9ldHv39eLm8vPw/no4OUX0mHYO/02pndjdZpfQ46bt8dBGrvTK9w4OoCqzLE209VMCFYMMoggWSTpfGAbSXZ7TqVn43saCOi@Lw9qDUFGw/UC2PSRZOi@ISCbPMFCKV@NUm5M@3u/UJqtDrh2CcRVYd@3ay5qyBXv3EVI7yvmJsGEuRLJxuA7rH4vFb2O@cFTQIbVL@1GbiZBPp9gatikpalgb2WJ1sk1B7@JNYF@NeLzAe717vY3ghL3yC6wXfd@rhXCq7EXZalJL8h8uFt5tFqlXq7NZLd9frX8B "Java (JDK) – Try It Online")
It was quite the struggle to get this golfed down. In particular, the imports involved with Collections.shuffle()/Arrays methods were too much to accept, so I had to create my own String shuffling algorithm (probably neither efficient nor uniformly distributed). Massive thanks to Steven for [proving any set of positions can be generated](https://cs.stackexchange.com/a/115439/110322) from the algorithm.
Formatted (with explanation):
```
(y, m, n) ->                                                   // y = yummies in the soup,
{                                                              // m = height, n = width
    for (m *= n; y.length() < m; y += " ")                     // set m to m*n and
        ;                                                      // add spaces to y to fill up
    var s = "";                                                // the rest of the soup
    for (; m-- > 0; y = s)                                     // for m*n iterations, scramble y
        for (var c : y.split(s = ""))                          // with random appends
            s = Math.random() < .5 ? s + c : c + s;
    s = "#".repeat(n);                                         // create the top/bottom of the rim
    return (s + y + s).replaceAll(".{" + n + "}", "\n#$0#"); // add all sides of the rim
};
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 27 bytes
```
ＮθＮη↖Ｂ⁺²θ⁺²η#ＦＳ«Ｗ℅ＫＫＪ‽θ‽ηＰι
```
[Try it online!](https://tio.run/##TYxNCsIwGAXX7SlC3XyBuqi40p0gqLS2@HOA2KYmmCZpTKognj1GUXA3w3tMzYipFRHer6V2duu6EzXQ43n87yx4oQYKs6POaWuDLtQdKuGuMElRj1P0YxY4GSXh0SqD4FPZW8PlGTBGjzi6MS4ogtI0XBIBFaWXsGC0cZ0@KNgR2agO3skvMhxiUeGE5Tp0LPDgT@@zLJ7Gq2Wel348iBc "Charcoal – Try It Online") Link is to verbose version of code. Takes input in the order width, height, string. Explanation:
```
ＮθＮη
```
Input the width and height.
```
↖Ｂ⁺²θ⁺²η#
```
Frame the bowl.
```
ＦＳ«
```
Loop over the characters in the string.
```
Ｗ℅ＫＫＪ‽θ‽η
```
Jump to a random position in the bowl until an empty spot is found.
```
Ｐι
```
Print the current character without moving the cursor.
[Answer]
# [Japt](https://github.com/ETHproductions/japt) [`-R`](https://codegolf.meta.stackexchange.com/a/14339/), ~~21~~ 18 [bytes](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)
```
úV*W ö¬òW ²Ô²û2W+2
```
[Try it](https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&flags=LVI&code=%2blYqVyD2rPJXILLUsvsyVysy&input=IkhFTExPIgo0CjEx)
```
úV*W ö¬òW ²Ô²û2W+2     :Implicit input of string U=S and integers V=M & W=N
úV*W                   :Right pad U with spaces to length V*W
     ö¬                :Random permutation
       òW              :Split to array of strings of length W
          ²            :Push 2
           Ô           :Reverse
            ²          :Push 2
             û2W+2     :Centre pad each element with "2" to length W+2
                       :Implicit output, joined with newlines
```
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~29 27~~ 19 bytes
```
pZ@iy~hw)1GeTT35&Ya
```
[Try it online!](https://tio.run/##y00syfn/vyDKIbOyLqNc09A9NSTE2FQtMvH//2hDYx1jw1gudX84iAABdQA "MATL – Try It Online")
Thanks @LuisMendo for -8 bytes!
Explanation: `p` computes the number of soup-pixels. Then `Z@` produces a random permutation of size of number of soup pixels. We will use this as indices to `iy~h` which is the input string with enough spaces added. `w)` swaps the two and indexes one with the other. We then reshape `1Ge` the shape into the desired rectangle and `#`-pad it using `TT35&Ya`. 
[Answer]
# [Icon](https://github.com/gtownsend/icon), ~~136~~ ~~133~~ ~~131~~ 118 bytes
```
procedure f(s,n,m)
s||:=repl(" ",m*n-*s)
!s:=:?s&\z
write(t:=repl(0,m+2))
write(0,s[1+(0to n)*m+:m],0)&\z
write(t)
end
```
[Try it online!](https://tio.run/##nZBfa4MwFMXf8ykyH0aiGWjbh@Eoo7O2alvdqnO6Pw@lpiAzsRjLoPS7uxSlG8ynHe5L8rvnntzk25I3zb4qtzQ7VBTukCCcMAzE6WSOK7ovkAIVwlR@owoMroQ5Nu/F9fsRfFV5TVHdNemEaQOMu1udiDdDQ3pdQo5Vppnsg@j4lwsDyrOmyPknrDY8Kxn4eQLb5BxhAKValh9pd94hZaIQaMjCd7CddSGOnbZs2MNoUZSSjmRDj3UyjX0vnDt25C5XcWKvo9QNvIUV@1Y4k7ZbaRv8tQUXJWed04cyvi/gwZras7njeovlyg8en9Zh9By/JOnrf8g5SO45Mtpv/AY "Icon – Try It Online")
[Answer]
# [C (clang)](http://clang.llvm.org/), ~~169~~ ~~...~~ 156 bytes
```
i,b;f(n,m,s)char*s;{char o[b=i=-~++n*(m+=3)],*a=o;for(srand(&a);--i;)*a++=i%m?-~i%m<3|i<m|i>m*n?35:32:10;for(*a=0;*s;*a=*a-32?*a:*s++)a=o+rand()%b;puts(o);}
```
[Try it online!](https://tio.run/##nU/JbsIwFLznK6JIVN4iYUylCpMiCmEN0AJNocDBbK2lxkFJOLH8euqkiA/oHN7zeDzz/Db25keorzSVZM33QJGAxHDzLSIU81PWzXCxdqRjXzFWCATYYXBFkHBCvg8jEEdCbcGDgNy2JYdIYOzIQlCzr7pW2VlWg7N8DpCqsccKK1VoMbdpf5HrCbojYbNSDYkKijGGOhfnkbCw5odjEoMQ8ksqVWIGQioAzZNh5N@Kk2ixcqz6S6Ppttqdbq/vDYaj17fxZPruf8zmn/9RLG7sQZlQSqyO63kjC2YXlGh@P7NMm/@xJ0JLxKo3/WFv0u6406438GfueDrvjnr9hj9sTFo3GyMsC7ljluGmUVKmRO@jmUa@tbVUS7VT2@yFqRHtkmOkzCI3Lukv "C (clang) – Try It Online")
Saved 7 @ceilingcat suggestion to use -~variable and auto storage for string o plus many improvements.
Saved 4 again from @ceilingcat 
Degolf : 
```
char*a,// pointer for set operations 
*o=malloc(b=i=(m+=3)*(n+=2));  => o[b=i=(m+=3)*-~++n]
// before allocating for the whole bowl as a char array
// increments m by 3 (2 for rims and 1 for '\n') and n by one but allocates for 2(rims)
// and assigns bowl size to i and b.
srand(time(0));// seeds rand function 
for(// loop to make empty bowl 
a=o;// using pointer as iterator
 --i ;)//  i decremented as a counter
 *a=// sets every char to..
 i%m?// if(not) over right side of bowl (m+3)
   -~i%m<3|i<m|i>m*n-m?35// if on rim '#'//-~i == (i+1)
   :32 // else ' ' 
  :10;// i%m==0
for(*a=0;// before loop terminates bowl with \0
 *s;// for every letters(exit on '\n')
 *a=*a-32?*a:*s++)
 // puts letter if bowl at a is a space and
 // go to next letter
 a=o+rand()%b; 
 // sets a to o offsetted by random
puts(o);// prints bowl 
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 16 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
P⁶ẋaẊs⁸ṪṾ€«”~ZƊ⁺
```
A dyadic Link accepting a list of integers, `[M, N]`, on the left and a list of characters, `S`, on the right which yields a list of lists of characters, the lines. Uses the tilde character, `~`, as the border.
**[Try it online!](https://tio.run/##AT8AwP9qZWxsef//UOKBtuG6i2Hhuopz4oG44bmq4bm@4oKswqvigJ1@WsaK4oG6/8OnWf//WzQsMTFd/ydIRUxMTyc "Jelly – Try It Online")**
All possible outputs have a non-zero chance of being yielded since we shuffle (`Ẋ`) a list of the characters of `S` along with the appropriate number of spaces.
The code `Ṿ€«”~ZƊ⁺` saves the byte which I imagine would be required to join with newlines that full programs using an integer such as zero would need to employ (e.g. `P⁶ẋaẊs⁸Ṫ;€0ZUƊ4¡Y` or `P⁶ẋaẊs⁸Ṫj@€Ø0Z$⁺Y`). Maybe there's a way to save more...?
[Answer]
# [C# (.NET Core)](https://www.microsoft.com/net/core/platform), 274 bytes
[Without LINQ]
Embarrassing number of bytes, but, this is what I got.
```
(x,y,z)=>{var f=new string('#',x+2)+'\n';char[] b=new string(' ',y*x).ToCharArray();Random r=new Random();while(z.Length>0){var d=r.Next(0,y*x);if(b[d]==' '){b[d]=z[0];z=z.Substring(1);}}z=f;for(var j=1;j<y*x+1;)z+=(j%x==1?"#":"")+b[j-1]+(j++%(x)==0?"#\n":"");return(z+=f);}
```
[Try it online!](https://tio.run/##fZHLauswEIb3eQrhUizVrrFDF6WqckgD4RR64yTQRZqFL3IsV5GMJCeOQ549R7a76aJFCM3o/@cbMUr1dSoVPdeaiQ1YHLShWzxKeaw1eFNyo@LtcQRAVSecpUCb2NhjJ1kGnmMmIOpEAOa1SO@ZMH63tVGW9XVMwCcgZ9j4B79FZHLcxQrkRNA9GHToXrh@442R534IF6dFrFZrkHxzANc/XDUoWMqZladKxQeI8L9YZHILVG8dEnu7LxinsA2eqNiYYhKivmNGVPBCGwPDnoRZDpNVtibEstGxD9tVuMYtaYNFnXw1jhA@nVqS41wq2GFKEuHy3hK8CKPWI7C8bAiJ/jgXzp3jIC9ZldfR2oOl513CBhESWulD9CJW1NRKQFuWW@4Zj4ZhBzMptOQ0eFfMUPgJb/0o9J2/lHP5LhXPHIR@9Ea3/tialwVV9FFP5/bDHoXNFrKufqsbD03eaEWfaFc1rSold1QvC6YXjHMmqNYPtXmRxuKGYb7mNpzJjP5GvvFvuvcwPbcUi6MPcs/7gpNd5/8 "C# (.NET Core) – Try It Online")
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~105~~ 78 bytes
Takes an array of characters and two integers; returns a string.
```
->s,h,w{((e=?#*w)+(s+[" "]*(h*w-s.size)).shuffle*""+e).gsub /.{#{w}}/,'#\&#
'}
```
[Attempt This Online!](https://ato.pxeger.com/run?1=m72kqDSpcsEiN9ulpSVpuhY3_XTtinUydMqrNTRSbe2Vtco1tTWKtaOVFJRitTQytMp1i_WKM6tSNTX1ijNK09JyUrWUlLRTNfXSi0uTFPT1qpWry2tr9XXUlWPUlLnUayGm7ikoLSlWcItWLY_2UHBV8AFC_1gdBRMdBUPDWIiSBQsgNAA)
]