# 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. Aug 3, 2011 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? Aug 3, 2011 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. Aug 4, 2011 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). Aug 4, 2011 at 17:25
• +1 for the first sentence: it actually took me a few seconds to realize it was spelled wrong XP Aug 4, 2011 at 18:33

# VBA, 128 177 151 chars

I know this is an older puzzle, but I wanted to add my two cents from

Sub o(s)
n=Left(s,1)
p=Len(s)-1
s=Right(s,p)
For i=1 To p-1
p=p-1
r=Int(p*Rnd()+1)
n=n & Mid(s,r,1)
s=Left(s,r-1) & Right(s,p-r+1)
Next
s=n & s
End Sub


Example Usage:

a = "According"
o a ' a is assigned by the passing of the reference to the 'o' sub.
a = "to"
o a ' see above...
a = "some"
o a
a = "controversial"
o a
a = "story"
o a


I was actually happily surprised to see it fare as well as it did against some of the other, more typical CG languages. After improving, this is still not the shortest, but I was happy to do it.

• Does that keep the first and last letters in place and work with strings less than 3 characters long? Mar 19, 2012 at 21:34
• D'oh! First and last don't keep, but length is not a problem. I'll get back to you... Mar 19, 2012 at 21:35
• Fixed, @Tomalak. Thanks for catching that. Mar 20, 2012 at 13:10

# C# w/Linq - 152 non-whitespace chars.

It's terrible compared to other languages on char count, but elegant:

public string Shuf(string i)
{
return new String(i.Take(1)
.Concat(i.Skip(1).Take(i.Length-2).OrderBy(x=>Guid.NewGuid()))
.Concat(new[]{i.Last()})
.ToArray());
}

• Why is the toArray necessary? Aug 3, 2011 at 20:22
• Because the product of these Linq methods is an IEnumerable<char>, for which there isn't a built-in String constructor. It has to be converted to an explicit char[]. Aug 3, 2011 at 20:35
• there's no Rand class in C# - it's Random. Also, name the function S instead of Shuf to gain some chars. May 15, 2012 at 7:06
• also, for a reason I haven't discovered yet, x=>new Random().Next() does not actually randomize the string. Try _=>Guid.NewGuid() - it's shorter and works May 15, 2012 at 7:11
• It would fail because each new Random() instance is being "seeded" with the same system time value as the last one (or the next one) and so each PRNG produces the same number sequence. May 15, 2012 at 17:10

# PHP 7.1, 54 bytes

If the word has less than 4 letters, don´t shuffle:

$r=$w[3]?$w[0].str_shuffle(substr($w,1,-1)).$w[-1]:$w;


# ><>, 19 bytes

{o&v
?vo>xl2(
&<oo{


Try it online!

Works for words of less than 3 length.

# R, 93 79 bytes

function(x,l=nchar(x))"if"(l<4,x,intToUtf8(utf8ToInt(x)[c(1,sample(l-2)+1,l)]))


Try it online!

Wroks for any ipnut szie dwon to zero, by frsit ckciheng the lgnteh of the sintrg and rneturing it if nchar(x)<4

-14 bytes thanks to Giuseppe!

• 89 bytes changing the sampling a bit Jul 17, 2018 at 20:40
• Oops, 83 bytes Jul 17, 2018 at 20:41
• Aaaand another one for good measure: 79 bytes -- in all fairness to me, I haven't gotten much sleep the last few days. Jul 17, 2018 at 20:48
• @Giuseppe This is much better indeed! Jul 18, 2018 at 0:23

# Python 3, 75 73 bytes

Thanks to @WW for saving me 2 bytes

lambda x:x[0]+''.join(sample(x[1:-1],len(x)-2))+x[-1]
from random import*


Try it online!

• You can remove the s= to save 2 bytes. Jul 18, 2018 at 3:09
• @WW I see that you could do that if the import wasn't there but how would you call it in in the "Try it online!" Jul 18, 2018 at 3:21
• Try it online! Jul 18, 2018 at 3:22
• @WW I see now Thank You! Jul 18, 2018 at 3:22

## JavaScript, 102 bytes

(_,a=[..._].slice(1,-1))=>_.replace(/./g,(m,i)=>(l=a.length,!i||!l?m:a.splice(~~(Math.random()*l),1)))


Try it online!

Using spread syntax and .slice() create array from input string beginning at index 1 through -1, .splice() elements from array within .replace() callback function, return string.

# APL(NARS), 52 chars, 104 bytes

∇r←s w;x
r←,w⋄→0×⍳3≥⍴w⋄r←(↑w),x[?⍨⍴x←¯1↓1↓w],¯1↑w
∇


This 'solution' is based to the fact that 3?3 return a random permutation of 1 2 3;
6?6 a random permutation of 1 2 3 4 5 6 ecc n?n a random permutation of 1 2 .. n so if B is a string B[(⍴B)?⍴B] would be a string random permutation of B. The function 's' has to have as input one string and return one string or ''. If someone see some error, please to say, thank you.

test:

  ⎕fmt s¨'' 'w' 'my' 'the' 'this' 'this' 'this'
┌7────────────────────────────────────────────┐
│┌0┐ ┌1─┐ ┌2──┐ ┌3───┐ ┌4────┐ ┌4────┐ ┌4────┐│
││ │ │ w│ │ my│ │ the│ │ tihs│ │ this│ │ this││
│└¯┘ └──┘ └───┘ └────┘ └─────┘ └─────┘ └─────┘2
└∊────────────────────────────────────────────┘
s¨'random' 'random' 'random' 'random'
rdonam rodanm raodnm rodnam
s 'permutation'
ptaemutroin


## JavaScript, 93 bytes

(_,[a,[...b],c,d=b.sort(_=>Math.random()-.5).join]=_.match(/(^.)|[^\1]+(?=.$)|.$/g))=>a+d+c


Try it online!

Using .match() with regular expression /(^.)|[^\1]+(?=.$)|.$/g to match first character, one or more characters that at not the first character followed by one character and end of string, and character followed by end of string and .sort() approach used at the question.

# 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
#  i.e. "a" and [1,-1,1] → ["a","",""]
€       # Map each value to:
.r     #  Randomly shuffle the characters
#   i.e. ["a","",""] → ["a","",""]
J    # Join the values in the list together (and output implicitly)
#  i.e. ["h","oohbtwtiua","s"] → "hoohbtwtiuas"
#  i.e. ["a","",""] → "a"


# Pyth, 18 bytes

KhQ=Z>1Q++KO.pPtQZ


Try it online!

# K (ngn/k), 22 bytes

{,/0N?'(0 1,1|#1_x)_x}


Try it online!

hat-tip ovf from the array programming discord / matrix for this answer!

Takes a single word to shuffle/randomize.

• (...)_x cut x (the input) on the indices from (...), returning a three-item list containing the first element, the middle element(s), and the last element
• (0 1,1|#1_x) generate a three-item list equivalent to [0, 1, max(1, len(x)-1)]. taking the max with 1 ensures single-character strings (e.g. ,"a") are handled as well.
• 0N?' shuffle each slice; this is a no-op on empty and one-character strings
• ,/ flatten the shuffled slices into a single string and (implicitly) return it

# APL, 27 bytes

{3≥⍴⍵:⍵⋄⍵[⍋0,(?⍨2-⍨⍴⍵),⍴⍵]}


# JavaScript, 81 bytes

s=>s.length<4?s:s[0]+[...s.slice(1,-1)].sort(_=>Math.random()>.5).join+s.at(-1)


Try it:

f=s=>s.length<4?s:s[0]+[...s.slice(1,-1)].sort(_=>Math.random()>.5).join+s.at(-1)

;[
'',
'1',
'12',
'123',
'1234',
'12345',
'123456',
'1234567',
'12345678',
'123456789',
].forEach(s=>console.log(f(s)))

# JavaScript, 4 bytes

s=>s


It is funny but in real the chance to randomly sort the symbols position in string and get the same string is equal to get the another string. And this is not depend on how many times we will randomize the symbols in string. It may seem like something unreal, but that's the way it is :)

To understand it more easy way imagine that we must generate a number by generating random digits. Let's say we have to get a number of length n. We have 10 digits, so in each position the chance of any digit is $$\\frac{1}{10}$/extract_tex] so the total chance to get the any number with length of n is $$\(\frac{1}{10})^n\$$. So the chance to get the number 8888888888888888...8888 randomly is the same as the chance to get 9872346897621449...0467. It is important to understand that the probability of the next digit is independent of the previous generated digit # C (gcc), 71 bytes Look mom, I beat python! f(s,d)char*s;{for(;s[2];)if(d=rand()%~-strlen(++s))*s^=s[d]^=*s^=s[d];}  Try it online! • Christ, I was expecting the C answer to be a lot longer than that ... Mar 10 at 6:33 # Thunno 2j, 10 bytes Dḣ?Ṫsḣµrh  Attempt This Online! #### Explanation Dḣ?Ṫsḣµrh # Implicit input D # Duplicate the input ḣ # Pop one copy and check if it's length is more than 1 ? # If that's true: Ṫ # Remove the last character and push it separately s # Swap so the last character is below the rest of the string ḣ # Discard the first character from this string µr # Randomly shuffle the string h # Push the first character of the input again # Implicit output of joined stack  # Python - 10396908885 109 characters import random as r def s(x): if len(x)>3:y=list(x[1:-1]);r.shuffle(y);return x[0]+''.join(y)+x[-1] return x  props to @dr jimbob for the "import as" bit and for catching my non-conformance with the spec. props also to @user unknown for getting the spec clarified. Edit: updated to conform to short-words spec. • Sorry about the other comment; my mistake; though I still think you need a return x[0]+''.join(y)+x[-1] at the end; also could change y=[x[a] for a in range(1,len(x))] to y=[x[1:-1]] Aug 3, 2011 at 17:18 • The [1:-1] actually doesn't work, and results in ['hateve'] for input of 'whatever'. My bad on the last letter, good catch. Aug 3, 2011 at 19:28 • I meant y=list(x[1:-1]). But you are supposed to not shuffle the first and last letter, so you need to change your return to return x[0]+''.join(y)+x[-1] Aug 3, 2011 at 19:55 • nice list(). I had [b for b in x[1:-1]] for a while there instead. Aug 3, 2011 at 20:05 • Doesn't work for input like 'I'; return 'II'. Aug 4, 2011 at 3:24 # Go, 154 bytes import."math/rand" func f(s string)string{k:=[]rune(s[1:len(s)-1]) Shuffle(len(k),func(i,j int){k[i],k[j]=k[j],k[i]}) return s[:1]+string(k)+s[len(s)-1:]}  Attempt This Online! # J, 18 bytes ({~>:,~0,1+?~)_2+#  Try it online! Constructs random indexes for the interior, prepends 0, appends n-1, then uses all those to index into the input. # GolfScript, 26 bytes (:f;):l;{;9rand}f l@$''+


Try it online!

# Zsh +coreutils, 73 bytes

for n;printf $n[1]$(fold -1<<<${n:1:-1}|shuf|tr -d \\n)${n:$#n-1:$#n-1}\


Incidentally, the Zsh documentation mixes up the descriptions of flags. F splits, f joins.