A code golf challenge, m'kay

APL (66)

{∊⍉⍵⍪⍉⍪(¯1+⌈?2×⍵∊',.!?')/¨{' ',⍵,⍨'''kay',⍨'mM'[1+⍵≠',']/⍨?3}¨⍵}⍣≢

Result of 10 runs:

      ↑ ({∊⍉⍵⍪⍉⍪(¯1+⌈?2×⍵∊',.!?')/¨{' ',⍵,⍨'''kay',⍨'mM'[1+⍵≠',']/⍨?3}¨⍵}⍣≢)¨ 10/⊂'Test, test. Test! Test?'
Test, m'kay, test. Test! Test?                  
Test, test. M'kay. Test! MMM'kay! Test? M'kay?  
Test, mm'kay, test. Test! MM'kay! Test? MM'kay? 
Test, mmm'kay, test. Test! Test? M'kay?         
Test, mm'kay, test. Test! Test? M'kay?          
Test, test. MM'kay. Test! Test? MMM'kay?        
Test, test. MMM'kay. Test! MMM'kay! Test? M'kay?
Test, test. Test! MM'kay! Test?                 
Test, mm'kay, test. M'kay. Test! Test?          
Test, test. MM'kay. Test! MM'kay! Test?   

Explanation:

  • {...}⍣≢: apply the function to the input until the value changes
    • Generate a M'kay for each character:
    • {...}¨⍵: for each character in the input:
      • 'mM'[1+⍵≠',']/⍨?3: generate 1 to 3 ms or Ms depending on whether the character was a comma or not.
      • '''kay',⍨: append the string 'kay.
      • ⍵,⍨: append the character
      • ' ',: prepend a space.
    • (¯1+⌈?2×⍵∊',.!?')/¨: for each M'kay', if its corresponding character is one of .,!?, select it with 50% chance, otherwise select it with 0% chance.
    • ⍉⍵⍪⍉⍪: match each selection with its character,
    • : list all the simple elements (characters) in order.

CJam, 65 52 49 bytes

l{_{_",.?!"#:IW>)mr{SI'M'm?3mr)*"'kay"3$}&}%_@=}g

Try it online in the CJam interpreter.

How it works

l            e# Read a line from STDIN.
{            e# Do:
  _          e#   Duplicate the line.
  {          e#   For each of its characters:
    _",.?!"# e#     Find its index in that string.
    :IW>     e#     Save the index in I and check if it's greater than -1.
    )        e#     Add 1 to the resulting Boolean.
     mr      e#     Pseudo-randomly select a non-negative integer below that sum.
             e#     If I == -1 the result will always be 0.
    {        e#     If the result is 1:
      S      e#       Push a space.
      I'M'm? e#       Select 'm' if I == 0 (comma) and 'M' otherwise.
      3mr)   e#       Pseudo-randomly select an integer in [1 2 3].
      *      e#       Repeat the M that many times.
      "'kay" e#       Push that string. MMM'kay.
      3$     e#       Copy the proper punctuation.
    }&       e#
  }%         e#
  _          e#   Copy the resulting array.
  @=         e#   Compare it to the copy from the beginning.
}g           e# Repeat the loop while the arrays are equal.
             e# This makes sure that there's at least one m'kay. M'kay.

K5, 99 90 bytes

{f::0;{x;~f}{,/{f::f|r:(*1?2)&#&",.?!"=x;x,("";" ",((1+1?3)#"Mm"@x=","),"'kay",x)@r}'x}/x}

Well, someone needed to kick-start this!

Saved 9 bytes by using a less fancy method of uppercasing the M.

Explanation

{                                                                                        }  Define a function
 f::0;                                                                                      Set `f` (used to determine when to stop) to 0.
      {x;~f}{                                                                         }/x   While `f` is 0 (no "m'kay"s have been inserted), loop over the string argument
               {                                                                   }'x      For each character in the string
                       (*1?2)&#&",.?!"=x                                                    If we are at a punctuation character, generate a random number between 0 and 1
                     r:                                                                     and assign it to `r`
                f::f|                                                                       If the number is one, an "m'kay" will be inserted, so the outer while loop should exit after this
                                                            "Mm"@x=","                      If the punctuation is a comma, then use a lowecase `m`, otherwise use `M`
                                                    (1+1?3)#                                Repeat the `m` between 1 and 3 times
                                               " ",(                  ),"'kay",x            Join the "m'kay" string to the punctuation and prepend a space
                                         x,("";                                 )@r         If the random number is 1, append the "m'kay" string, to the current string
             ,/                                                                             Join the resulting string

99-byte version

{f::0;{x;~f}{,/{f::f|r:(*1?2)&#&",.?!"=x;x,("";" ",((1+1?3)#`c$(-32*~","=x)+"m"),"'kay",x)@r}'x}/x}