Background
There is a message that is circulating via public media that claims a reader can easily read a message where the inner letters of each words is scrambled, as long as the first and last letters remain the same and the word contains all the letters.

Another example shows that it is quite difficult to read the text where all the letters are reversed rather than scrambled.

In this kata we will make a generator that generates text in a similar pattern, but instead of scrambled or reversed, ours will be sorted alphabetically

Requirement
return a string where:
1) the first and last characters remain in original place for each word
2) characters between the first and last characters must be sorted alphabetically
3) punctuation should remain at the same place as it started, for example: shan't -> sahn't
Assumptions
1) words are seperated by single spaces
2) only spaces separate words, special characters do not,  for example: tik-tak -> tai-ktk
3) special characters do not take the position of the non special characters, for example: -dcba  ->  -dbca
4) for this kata puctuation is limited to 4 characters: hyphen(-), apostrophe('), comma(,) and period(.) 
5) ignore capitalisation


for reference: http://en.wikipedia.org/wiki/Typoglycemia

Source: codewars | Difficulty: EASY
Tags: Fundamentals

Starter code: def scramble_words(words):
	

Solutions:
import re

def scramble_words(words):

	def sort_letters(match):
		s = match.group()
		letters = iter(sorted(filter(str.isalpha, s[1:-1])))
		return s[0] + ''.join((next(letters) if c.isalpha() else c for c in s[1:-1])) + s[-1]
	return re.sub('[a-z][^\\s]*[a-z]', sort_letters, words)


sort_word = lambda w, l: (lambda a: ''.join((next(a) if c.isalpha() else c for c in w)))(iter(l[:len(l) > 1] + sorted(l[1:-1]) + l[-1:]))
scramble_words = lambda s: ' '.join((sort_word(w, list(filter(str.isalpha, w))) for w in s.split()))


import re

def scramble_words(words):
	new_words = []
	for word in words.split():
		(begin, word) = re.match("([-',.]*[a-zA-Z]?)(.*)", word).groups()
		(word, end) = re.match("(.*?)([a-zA-Z]?[-',.]*)$", word).groups() if word else ('', '')
		sorted_word = list(sorted((c for c in word if c.isalpha())))
		for (i, c) in enumerate(word):
			if c in "-',.":
				sorted_word.insert(i, c)
		new_words.append(begin + ''.join(sorted_word) + end)
	return ' '.join(new_words)


import string

def scramble_words(words):
	if len(words) <= 1:
		return words
	words = words.split(' ')
	pureWords = []
	sChars = []
	for i in range(len(words)):
		flag = 0
		for l in words[i][1:]:
			if l != words[i][0]:
				flag = 1
		if flag == 0:
			words[i] = words[i][0]
		pureWords.append('')
		for j in range(len(words[i])):
			if words[i][j] in string.ascii_letters:
				pureWords[i] += words[i][j]
			else:
				sChars.append((j, words[i][j]))
		if len(words[i]) == 1:
			pureWords[i] = words[i]
		else:
			pureWords[i] = pureWords[i][0] + ''.join(sorted(pureWords[i][1:-1])) + pureWords[i][-1]
			currWord = [l for l in pureWords[i]]
			for (index, char) in sChars:
				currWord.insert(index, char)
			pureWords[i] = ''.join(currWord)
		sChars = []
	return ' '.join(pureWords)


import re

def scramble_words(s):
	li = []
	for k in s.split():
		sp_chars = [[i, j] for (j, i) in enumerate(k) if not i.isalpha()]
		s = re.sub("[-,.']", '', k)
		result = [s[0]] + sorted(s[1:-1]) + [s[-1]]
		for (i, j) in sp_chars:
			result.insert(j, i)
		li.append([''.join(result), k][len(k) < 4])
	return ' '.join(li)


def sort_word(word):
	characters = [[], []]
	for char in word:
		characters[char.isalpha()].append(char)
	characters[1] = characters[1][:len(word) > 1] + sorted(characters[1][1:-1]) + characters[1][-1:]
	return ''.join((characters[char.isalpha()].pop() for char in reversed(word)))[::-1]

def scramble_words(words):
	return ' '.join(map(sort_word, words.split()))


SPECIAL = "-',."

def scramble_words(words):
	output = []
	for word in words.split():
		sortable = [c for c in word if c.isalpha()]
		typgly = sortable[:1] + sorted(sortable[1:-1]) + sortable[-1:]
		output.append(''.join((c if not c.isalpha() else typgly.pop(0) for c in word)))
	return ' '.join(output)


def scramble_words(words):
	sort = lambda x: x if len(x) < 3 else x[0] + ''.join(sorted(x[1:-1])) + x[-1]
	find = lambda x: [(i, y) for (i, y) in enumerate(x) if y in ".,'-"]
	mx = []
	for x in words.split():
		(l, f) = (list(''.join(sort([y for y in x if y not in ".,'-"]))), find(x))
		if f:
			l.insert(f[0][0], f[0][1])
		if len(f) == 2:
			l.insert(f[1][0], f[1][1])
		mx.append(''.join(l))
	return ' '.join(mx) if mx else ''


import string

def find_char_index(word, mode='f'):
	word = [x for x in word]
	if mode == 'f':
		for (index, char) in enumerate(word):
			if char in string.punctuation:
				continue
			else:
				return index
	else:
		word.reverse()
		for (index, char) in enumerate(word):
			if char in string.punctuation:
				continue
			else:
				return len(word) - (index + 1)

def scramble_words(sentence):
	words = sentence.split(' ')
	final = []
	for word in words:
		first_index = find_char_index(word, 'f')
		last_index = find_char_index(word, 'l')
		res = ''
		ext_char = []
		for (index, char) in enumerate(word):
			if char in string.punctuation or index == first_index or index == last_index:
				res += char
			else:
				res += '{}'
				ext_char.append(char)
		final.append(res.format(*sorted(ext_char)))
	return ' '.join(final)