Z̡̬a̧̯̔l̆̓g̛̘̟o̡ generator

CJam, 57 56 49 47 bytes

Thanks to Sp3000 for saving 7 bytes.

q{_eu_el={Pmrmc1.mrml-50*mq*A+mo{48mr'̀+}*}|}/

Test it here.

Explanation

This uses Box–Muller for the normal distribution: the basic algorithm generates two uniform variables in the range [0,1), U and V and then computes two normally distributed values from them. We only need one and the simpler one is X = √(-2 ln U) cos(2πV). This generates a distribution with mean 0 and standard deviation 1, so we need to multiply it by 5 to correct the standard deviation and add 10 to correct the mean. We can also simplify the cosine, because omitting the 2 gives the same distribution. So we compute X = √(-50 ln U) cos(πV) + 10 before rounding to get the number of combining marks.

Here is the code:

q{          e# For each character in the input...
  _eu_el=   e#   Make an upper case and a lower case copy and check if they are equal.
  {         e#   If they aren't... (i.e. if this is a letter)
    Pmr     e#     Generate a uniformly random value in [0,π).
    mc      e#     Take the cosine.
    1.mr    e#     Generate a uniformly random value in [0,1).
    ml      e#     Take the natural logarithm.
    -50*    e#     Multiply by -50.
    mq*     e#     Take the square root and multiply by the cosine.
    A+      e#     Add 10.
    mo      e#     Round to nearest integer.
    {       e#     That many times...
      48mr  e#       Generate a uniformly random integer in [0,47].
      '̀+    e#       Add it to the first combining mark.
    }*
  }|
}/

This means we just dump all the characters and combining marks on the stack in the correct order, where they are printed automatically at the end of the program.


Python3, 162 156 bytes

from random import*
q=lambda z:''.join([v,v+''.join(choice(list(map(chr,range(768,815))))for i in range(int(normalvariate(10,5))))][v.isalpha()]for v in z)

Possible usage:

print(q(u"Programming Puzzles and Code Golf"))

I import random, generate a string of all combining characters, return a random subset of combining characters according to mean 10, stddev 5 normal distribution and append to each alpha letter in then string, then join the results.

Test input:

Programming Puzzles and Code Golf

Test Output:

P̡̣̝̬̞̃̏̋r̫̤̒̇̋̂̉̔̂̕ó̘̫̔g̭̤̝̖̅̏̍̆̇̍ȑ̮̭̃̎̒̄̅̊̚ḁ̉̅̎̑m̧̠̤̎̒̅̂̓̒m̨̮̏̐̓̐̇ī̘̌́̄̆̋̏̉̇ń̝̀̑̔̅̏́̑̕g̢̞̬̥̜̩̖̎̍́ P̨̞̮̭̂̄̄ử̝̔̍̋̀̕zž̧̥́l̩̫̣̉̊̍̋̐̊̌ĕ̡̛̤̖̤̄̅̈̚s̨̨̞̝ ą̙̦̖̄̓̊̌̉̌n̢̙̜̪̤̣̪̔d̘̙̠̝̫̭̜̑̔̕ C̢̛̝̦̬̝̈̄̏̏ȏ̡̇̓̐̎̆̉̌̄d̗̝̞̤̟̭̓̐̈̕ė̡̛̜̥̥̠̟̦̌ G̖̟̘̅̄̈́̚o̧̗̬̗̥̞̙̐̌̊l̢̞̖̟̑̇f̢̛̩̀̒̃̌̈


MATLAB, 89 bytes

Credits go out to DankMemes, but as I am not able to comment yet I'm forced to place my improvements w.r.t. his MATLAB submission in a separate answer.

function o=z(a),o=[];for c=a,o=[o,c,randi(49,[1,isletter(c)*fix(normrnd(5,10))])+767];end

Slightly more golfed by replacing the newlines with commas and semicolons (which also suppresses the intermediate outcomes from the loop).

  • 9 bytes can be won by replacing isstrprop(c,'alpha') with isletter(c).
  • We don't need the dots in front of * and +, as we multiply with a scalar. That's another 2 bytes.
  • fix instead of floor for 2 bytes. It does give a slight bias towards 0 though, so alternatively ceil can be used to gain 1 byte.
  • I changed the random character pick to work with random integers between 1 and 49 to reduce the amount of operations and save some additional bytes.

Using it with

z('Simple check for proper functionality results in this beautiful text!')

Results in

Ś̜̬̭̃̑̓́̃i̩̰̗̙̫̜̇̀̑mplë̥̟̣̩̙̗̐̌̇ cḧ̢̛̰̝̣̝̋̋̑eç̛̞̖̖̰̰̝̭̞̜̝̥̋̎̇̄̂̆̆̔̎̊k̢̟̠̞̈̌̂ for̢̡̫̥̩ ṗ̝̥̗̬̯̯̝̍̑̈̊rop̡̡̨̢̝̫̤̠̫̠̏̎̄́̒ė̦̋̕ŕ̦̣̇̊ f̧̜̦̏̏̉̇unc̨̢̗̟̙̩̝̠̄̈̋̑̏̎̄̇̌̒́̇̚ti̝ỏ̧̯̰̥̣̜̎̓̀̊̔̒̉̔̑̑̔̋̚n̡̘̠̮̤̖̥̤̂̔̇̇al̩̫̇̇̔it̫̮̔̎̕y̡̰̰̦̔̇̏̎̋ r̛̙̯̉ĕ̬̟̉̓̌s̛̝̝̭ul̨̧̧̛̙̤̥̜̟̞̔̓̓̊̀̂t̡̠́̓̀̉̎̒̈̚ş̗̠̋̍̏̌̎̕ ǐ̛̗̭̪̤̃̏̍̎̈̓̐̚n̞̮̞̬̝̭̎̔̍ th̢̧̛̬̬̖̠̗̮̰̠̖̖̠̞̦̞̎̄̓̎̇̆̚̕is̟̬̍̂̎ bea̭̗̝ṳ̝̞̠̦̣̤̦̅̂̒̄̒̔̉̏tỉ̪̩̅̓̂f̢̝̰̬̤̰̊̊̉̎̕̕u̡̝̇l tex̰̤̥̍̕t̡̝̥̣̟̩̟̉̂̆̋̈̈̈̍̔!