Write a function that, given a string of text (possibly with punctuation and line-breaks),
returns an array of the top-3 most occurring words, in descending order of the number of occurrences.

Assumptions:
------------

- A word is a string of letters (A to Z) optionally containing one or more apostrophes (') in ASCII. (No need to handle fancy punctuation.)
- Matches should be case-insensitive, and the words in the result should be lowercased.
- Ties may be broken arbitrarily.
- If a text contains fewer than three unique words, then either the top-2 or top-1 words should be returned, or an empty array if a text contains no words.

Examples:
------------

```
top_3_words("In a village of La Mancha, the name of which I have no desire to call to
mind, there lived not long since one of those gentlemen that keep a lance
in the lance-rack, an old buckler, a lean hack, and a greyhound for
coursing. An olla of rather more beef than mutton, a salad on most
nights, scraps on Saturdays, lentils on Fridays, and a pigeon or so extra
on Sundays, made away with three-quarters of his income.")
# => ["a", "of", "on"]

top_3_words("e e e e DDD ddd DdD: ddd ddd aa aA Aa, bb cc cC e e e")
# => ["e", "ddd", "aa"]

top_3_words("  //wont won't won't")
# => ["won't", "wont"]
```

```if:java
For java users, the calls will actually be in the form: `TopWords.top3(String s)`, expecting you to return a `List`.
```

Bonus points (not really, but just for fun):
------------

1. Avoid creating an array whose memory footprint is roughly as big as the input text.
2. Avoid sorting the entire array of unique words.

Difficulty: MEDIUM
Tags: String algorithms

Starter code:
def top_3_words(text):
	

Solutions:
from collections import Counter
import re

def top_3_words(text):
	c = Counter(re.findall("[a-z']+", re.sub(" '+ ", ' ', text.lower())))
	return [w for (w, _) in c.most_common(3)]


import re
from collections import Counter
top_3_words = lambda t: [w for (w, c) in Counter(re.findall("'*[a-z][a-z']*", t.lower())).most_common(3)]


import re
from collections import Counter

def top_3_words(text):
	words = re.findall("[a-z']*[a-z]+[a-z']*", text.lower())
	top_3 = Counter(words).most_common(3)
	return [tup[0] for tup in top_3]


from collections import Counter
import re

def top_3_words(text):
	words = re.findall("[a-z][a-z']*|[a-z']*[a-z]", text, re.IGNORECASE)
	topchart = Counter([word.lower() for word in words]).most_common(3)
	return [top[0] for top in topchart]


import re

def top_3_words(text):
	re_non_valid = re.compile("[^a-z' ]")
	re_chars = re.compile('[a-z]')
	text = text.lower()
	text = ' '.join([x for x in re_non_valid.sub(' ', text).split() if re_chars.search(x)])
	words = {}
	top = {}
	for word in text.split():
		if word in words:
			words[word] += 1
		else:
			words[word] = 1
		top[word] = words[word]
		if len(top) > 3:
			top.pop(min(top, key=top.get))
	return sorted(top, key=top.get, reverse=True)


from collections import Counter
from string import ascii_letters, printable
keep = ascii_letters + "'"
remove = printable.translate(str.maketrans('', '', keep))
table = str.maketrans(keep + remove, keep.lower() + ' ' * len(remove))

def top_3_words(text):
	words = (word for word in text.translate(table).split() if set(word) != {"'"})
	return [word for (word, freq) in Counter(words).most_common(3)]


from operator import itemgetter

def top_3_words(text):
	text0 = ''.join([c if c in "abcdefghijklmnopqrstuvwxyz'" else ' ' for c in text.lower()])
	check_dict = {}
	text0 = text0.split()
	for x in text0:
		if not any((i.isalpha() for i in x)):
			text0.pop(text0.index(x))
	for x in text0:
		if x in check_dict:
			check_dict[x] += 1
		else:
			check_dict.update({x: 1})
	top_3_list = list(sorted(list(check_dict.items()), key=itemgetter(1), reverse=True)[:3])
	return list(map(itemgetter(0), top_3_list))


from string import punctuation

def top_3_words(text):
	for p in punctuation:
		if p != "'":
			text = text.replace(p, ' ')
	count = {}
	for w in text.lower().split():
		if w.strip(punctuation) == '':
			pass
		elif w in count.keys():
			count[w] += 1
		else:
			count[w] = 1
	lcount = [(w, c) for (w, c) in count.items()]
	lcount.sort(key=lambda x: x[1], reverse=True)
	return [x[0] for x in lcount[:3]]


from collections import Counter as C
from re import sub as s
from string import punctuation as p

def top_3_words(__):
	__ = s('[{}]'.format(p.replace("'", '')), ' ', __).lower()
	return list(filter(lambda c: c.replace("'", '').isalnum(), (_[0] for _ in C(__.split()).most_common(3))))


import re

def top_3_words(text):
	panctuation = "_'"
	list_word = re.findall("[a-z0-9A-Z\\']+", text.lower())
	result = []
	dict1 = {}
	for word in list_word:
		if word and word != "'" and (word != "'''"):
			if word in dict1:
				dict1[word] += 1
			else:
				dict1[word] = 1
	result = sorted(list(dict1.items()), reverse=True, key=lambda x: x[1])
	result = result[:3] if len(result) > 3 else result
	return [res[0] for res in result]