# Cambridge Transposition

I'm sure most, if not all, of you have come across this at some point or another:

Aoccdrnig to a rscheearch at Cmabrigde Uinervtisy, it deosn't mttaer in waht oredr the ltteers in a wrod are, the olny iprmoetnt tihng is taht the frist and lsat ltteer be at the rghit pclae. The rset can be a toatl mses and you can sitll raed it wouthit porbelm. Tihs is bcuseae the huamn mnid deos not raed ervey lteter by istlef, but the wrod as a wlohe.

• Create a program that inputs any amount of text. For testing purposes, use the unscrambled version of the above text, found below.

• The program must then randomly transpose the letters of each word with a length of 4 or more letters, except the first and last letter of each word.

• All other formatting must remain the same (capitalization and punctuation, etc.).

Testing text:

According to a researcher at Cambridge University, it doesn't matter in what order the letters in a word are, the only important thing is that the first and last letter be at the right place. The rest can be a total mess and you can still read it without problem. This is because the human mind does not read every letter by itself but the word as a whole.

As usual, this is a code-golf. Shortest code wins.

-
Similar to How to randomize letters in a word, though in that one only a single word needs to be scrambled whereas here it's every word in a sentence. – Gareth Dec 20 '12 at 16:44
I agree. The questions are similar enough that solutions for one problem can be used almost directly for the other. – primo Dec 20 '12 at 17:25
Last letter is not right in `rscheearch` in your sample text. – daniero Dec 20 '12 at 19:26
I'd be more impressed with a program that did the reverse (i.e. input is the scrambled text). – Mr Lister Dec 21 '12 at 13:38
Must the position of the apostrophe in `don't` remain in the same position? The spec says `All other formatting must remain the same (capitalization and punctuation, etc.).` but I'm not sure how that works out here... – Gaffi Mar 20 '13 at 17:25

## Ruby - 50 48 chars, plus `-p` command line parameter.

``````gsub(/(?<=\w)\w+(?=\w)/){[*\$&.chars].shuffle*''}
``````

Thanks @primo for -2 char.

## Test

``````➜  codegolf git:(master) ruby -p 9261-cambridge-transposition.rb < 9261.in
Acdrcinog to a racreseher at Cagribmde Ursvetniiy, it dsoen't mttaer in waht odrer the leertts in a word are, the olny ionarpmtt tnhig is that the fsirt and last letetr be at the rghit pcale. The rset can be a taotl mses and you can slitl raed it wthiuot perlbom. Tihs is buaecse the hmuan mind does not raed ervey lteetr by ietlsf but the word as a wlhoe.
``````
-
Ruby doesn't support `\K` for zero-width look-behind assertion? Also, the innermost grouping is unnecessary, using `\$&` instead of `\$1`. – primo Dec 20 '12 at 17:47
@primo, I think not, it doesn't work, and neither have I found it in any reference page. Thanks for `\$&` tip :) – Dogbert Dec 20 '12 at 18:17
You're right. I guess I assumed they had taken perl regex directly, as php does ;) – primo Dec 20 '12 at 19:01
tell me more about this `codegolf` script – Sparr Feb 2 at 17:27

## PHP 84 bytes

``````<?for(;\$s=fgets(STDIN);)echo preg_filter('/\w\K\w+(?=\w)/e','str_shuffle("\0")',\$s);
``````

Using a regex to capture words that are at least 4 3 letters long, and shuffling the inner characters. This code can handle input with multiple lines as well.

If only one line of input is required (as in the example), this can be reduced to 68 bytes

``````<?=preg_filter('/\w\K\w+(?=\w)/e','str_shuffle("\0")',fgets(STDIN));
``````

There's only one letter in the middle, so it doesn't matter if you shuffle it.

-

## J (48)

``````''[1!:2&4('\w(\w+)\w';,1)({~?~@#)rxapply 1!:1[3
``````

Explanation:

• `1!:1[3`: read all input from stdin
• `rxapply`: apply the given function to the portions of the input that match the regex
• `({~?~@#)`: a verb train that shuffles its input: `#` counts the length, this gets applied to both sides of `?` giving N distinct numbers from 0 to N, `{` then selects the elements at those indices from the input array.
• `('\w(\w+)\w';,1)`: use that regex but only use the value from the first group
• `[1!:2&4`: send unformatted output to stdout
• `''[`: suppress formatted output. This is necessary because otherwise it only outputs that part of the output that fits on a terminal line and then ends with `...`.
-

# Python, 118

Python is terribly awkward for things like this!

``````from random import*
for w in raw_input().split():l=len(w)-2;print l>0and w[0]+''.join((sample(w[1:-1],l)))+w[-1]or w,
``````

### Bonus

I tried some other things that I thought would be clever, but you have to import all sorts of things, and a lot of methods don't have return values, but need to be called separately as its own statement. The worst is when you need to convert the string to a list and then `join`ing it back to a string again.

Anyways, here are some of the things that I tried:

Regex!
``````import re,random
def f(x):a,b,c=x.group(1,2,3);return a+''.join(random.sample(b,len(b)))+c
print re.sub('(\w)(\w+)(\w)',f,raw_input())
``````
Permutations!
``````import itertools as i,random as r
for w in raw_input().split():print''.join(r.choice([x for x in i.permutations(w)if w[0]+w[-1]==x[0]+x[-1]])),
``````
You can't shuffle a partition of a list directly and `shuffle` returns `None`, yay!
``````from random import*
for w in raw_input().split():
w=list(w)
if len(w)>3:v=w[1:-1];shuffle(v);w[1:-1]=v
print ''.join(w),
``````
-
+1 for your tenacity! – jdstankosky Mar 19 '13 at 15:39

## APL, 58 49

I believe this works in IBM APL2 (I don't have IBM APL)

``````({⍵[⌽∪t,⌽∪1,?⍨t←⍴⍵]}¨x⊂⍨~b),.,x⊂⍨b←' ,.'∊⍨x←⍞,' '
``````

If not, then in Dyalog APL, add to the front:

`````` ⎕ML←3⋄
``````

This assumes the only non-word characters are space, comma, and period.

-
Still golfable, but I don't have APL symbols on iPhone... – TwiNight Dec 28 '12 at 12:01

## APL 107

Unfortunately my APL interpreter does not support regexs so here's a home rolled version where the text to be scrambled is stored in the variable t:

``````⎕av[((~z)\(∊y)[∊(+\0,¯1↓n)+¨n?¨n←⍴¨y←(~z←×(~x)+(x>¯1↓0,x)+x>1↓(x←~53≤(∊(⊂⍳26)+¨65 97)⍳v←⎕av⍳,t),0)⊂v])+z×v]
``````

Essentially the code partitions the text into words based on the letters of the alphabet only and then into the letters between the first and last letters of those words. These letters are then scrambled and the whole character string reassembled.

-

## R, 179

Using the function I wrote for the randomize letters in a word problem:

Input:

``````s <- "According to a researcher at Cambridge University, it doesn't matter in what order the letters in a word are, the only important thing is that the first and last letter be at the right place. The rest can be a total mess and you can still read it without problem. This is because the human mind does not read every letter by itself but the word as a whole."
``````

Solution:

``````f=function(w){l=length;s=strsplit(w,"")[[1]];ifelse(l(s)<3,w,paste(c(s[1],sample(s[2:(l(s)-1)]),s[l(s)]),collapse=""))}
g=Vectorize(f)
paste(g(strsplit(s," ")[[1]]), collapse=" ")
``````

Result:

``````[1] "Arioccdng to a reehaecrsr at Cabrgimde Uveirisnyt, it des'not mttear in waht odrer the lttrees in a wrod are, the olny inpotmart thnig is that the fsrit and lsat letetr be at the right palce. The rset can be a toatl mses and you can stlil raed it wutioht pmrlebo. This is bsuceae the hmuan mnid deos not read ervey lteetr by iesltf but the word as a wleho."
``````
-

## VBA, 351 373/409

``````Sub v(g)
m=1:Z=Split(g," "):j=UBound(Z)
For u=0 To j
t=Z(u):w=Len(t):l=Right(t,1):If Not l Like"[A-Za-z]" Then w=w-1:t=Left(t,w):e=l Else e=""
If w>3 Then
n=Left(t,1):p=w-1:s=Right(t,p):f=Right(t,1)
For p=1 To p-1
q=w-p:r=Int((q-1)*Rnd())+1:n=n & Mid(s,r,1):s=Left(s,r-1) & Right(s,q-r)
Next
Else
n=t:f=""
End If
d=d & n & f & e & " "
Next
g=d
End Sub
``````

Alternate (larger) Method:

``````Sub v(g)
m=1:Z=Split(g," "):j=UBound(Z)
For u=0 To j
t=Split(StrConv(Z(u),64),Chr(0)):w=UBound(t)-1:l=Asc(t(w)):If l<64 Or (l>90 And l<97) Or l>122 Then e=t(w):w=w-1 Else e=""
If w>3 Then
n=t(0):p=w-1:s=""
For i=-p To -1
s=t(-i) & s
Next
f=t(w)
For p=1 To p-1
r=Int((w-p)*Rnd())+1:n=n & Mid(s,r,1):s=Left(s,r-1) & Right(s,w-p-r)
Next
n=n & s
Else
n=Z(u):f="":e=""
End If
d=d & n & f & e & " "
Next
g=d
End Sub
``````

Both of these methods change the value of the variable passed to the `Sub`. i.e.

``````Sub Test()
strTestString = "This is a test."
v strTestString
Debug.Print strTestString
End Sub
``````

will output something like this:

``````"Tihs is a tset."
``````

Also, this does randomize mid-word punctuation, so this may not fit the spec 100%.

-

# Pyth, 23 bytes

``````jdm?gld4++hd.<Ptd1eddcz
``````

Non-competing because Pyth was made after this challenge was posted.

Try it online

-