# How to randomize letters in a word

According to some controversial story, the odrer of ltteres in a wrod deos not mttaer much for raednig, as lnog as the frist and lsat lteter macth with the orignial wrod.

So, for fun, what would be the shortest function to randomize letter order in a word while keeping the first and the last letter in place?

Here's my stab at it with JavaScript. All whitespace removed it's at 124 130 characters.

function r(w) {
var l=w.length-1;
return l<3?w:w[0]+w.slice(1,l).split("").sort(function(){return Math.random()-.5}).join("")+w[l];
}


Shorter JavaScript always welcome.

• Edit: length check added. Function should not fail for short words.
• Haskell, 4 characters: r=id. – Thomas Eding Aug 3 '11 at 20:01
• Yes. It returns the exact same thing as the input. On another note, what do we do about punctuation? Do we only operate on words consisting only of letters? – Thomas Eding Aug 3 '11 at 20:28
• @trinithis not sure what you talking about, but id is the identity function. I would still like to see Haskell solution to this problem in less than 100 characters. – Arlen Aug 4 '11 at 7:37
• Should the specification be updated to require a uniform distribution of outcomes? This would disallow the 4 character Haskell solution. It would also disallow your example Javascript solution (shuffling by doing a sort like that is not uniform). – Thomas Eding Aug 4 '11 at 17:25
• +1 for the first sentence: it actually took me a few seconds to realize it was spelled wrong XP – Nate Koppenhaver Aug 4 '11 at 18:33

# Coffee-script: 76 91 Bytes

f=(a)->a.length>1&&a[0]+(a.split('')[1..-2].sort ()->.5-Math.random()).join('')+a[-1..]||a


Wow, I like this language already.

## ><>, 40 bytes

_5l)?vl1-[&r02.
} .32<

# Javascript 98 bytes

a=>{c=l=a.length-1;for(b=[a[0]];--c;)d=Math.random()*99|0,b[d]?c++:b[d]=a[c];return b.join+a[l]}


Try it online!

This assigns each letter other than the first and last to a random array index, and then joins the array into a string. 99 can be changed to 9e9 to work on (much!) longer words at the cost of a byte, but then join takes almost a minute. Besides, there aren't many words that even approach 100 characters.

Because of that, this is 12 bytes shorter (86 bytes) and works almost every time:

a=>{c=l=a.length-1;for(b=[a[0]];--c;)b[Math.random()*9e9|0]=a[c];return b.join+a[l]}


# 05AB1E, 12 11 bytes

g≠ićs¨.rIθJ


Fun 12 11 bytes alternative:

gÍ¸1.ø£€.rJ


Both version also work for strings with less than 3 characters. The first one could be just ćs¨.rIθJ (8 bytes), but then it doesn't work for single-character strings ("a" becomes "aa").

Explanation:

g              # Take the length of the (implicit) input
#  i.e. "a" → 1
≠i            # If this length is not 1:
#   i.e. 12 → 1 (truthy)
#   i.e. 1 → 0 (falsey)
ć           #  Extract the head of the (implicit) input
s          #  Swap so the list (minus head) is at the top of the stack again
¨         #  Remove the last character
.r       #  Randomly shuffle the characters
Iθ     #  Take the last character of the input
J    #  Join the values on the stack together (and output implicitly)
#   i.e. "h", "oohbtwtiua", "s" → "hoohbtwtiuas"
# (Implicit else)
#  (Output the input as is implicitly)
#   i.e. "a"


g              # Take the length of the (implicit) input
#  i.e. "a" → 1
Í             # Subtract 2
#  i.e. 12 → 10
#  i.e. 1 → -1
¸            # Wrap it into a list
#  i.e. 10 → [10]
#  i.e. -1 → [-1]
1.ø         # Surround it with 1s
#  i.e. [10] → [1,10,1]
#  i.e. [-1] → [1,-1,1]
£        # Split the (implicit) input into parts of that size