To participate in a prize draw each one gives his/her firstname. 

Each letter of a firstname
has a value which is its rank in the English alphabet. `A` and `a` have rank `1`, `B` and `b` rank `2` and so on. 

The *length* of the firstname is added to the *sum* of these ranks hence a number `som`. 

An array of random weights is linked to the firstnames and each `som` is multiplied by 
its corresponding weight to get what they call a `winning number`.

Example:
```
names: "COLIN,AMANDBA,AMANDAB,CAROL,PauL,JOSEPH"
weights: [1, 4, 4, 5, 2, 1]

PauL -> som = length of firstname + 16 + 1 + 21 + 12 = 4 + 50 -> 54
The *weight* associated with PauL is 2 so PauL's *winning number* is 54 * 2 = 108.
```
Now one can sort the firstnames in decreasing order of the `winning numbers`. When two
people have the same `winning number` sort them *alphabetically* by their firstnames.

### Task:

- parameters: `st` a string of firstnames, `we` an array of weights, `n` a rank 

- return: the firstname of the participant whose rank is `n` 
(ranks are numbered from 1)

### Example:
```
names: "COLIN,AMANDBA,AMANDAB,CAROL,PauL,JOSEPH"
weights: [1, 4, 4, 5, 2, 1]
n: 4

The function should return: "PauL"
```
# Notes:
- The weight array is at least as long as the number of names, it can be longer.

- If `st` is empty return "No participants".

- If n is greater than the number of participants then return "Not enough participants".

- See Examples Test Cases for more examples.

Source: codewars | Difficulty: EASY
Tags: String algorithms

Fundamentals

Sorting

Starter code: def rank(st, we, n):
	

Solutions:
def rank(st, we, n):
	if not st:
		return 'No participants'
	if n > len(we):
		return 'Not enough participants'
	name_score = lambda name, w: w * (len(name) + sum([ord(c.lower()) - 96 for c in name]))
	scores = [name_score(s, we[i]) for (i, s) in enumerate(st.split(','))]
	scores = list(zip(st.split(','), scores))
	scores.sort(key=lambda x: (-x[1], x[0]))
	return scores[n - 1][0]


def win_num(name, weight):
	return (len(name) + sum((ord(c) - 96 for c in name.lower()))) * weight

def rank(st, we, n):
	if not st:
		return 'No participants'
	elif n > len(we):
		return 'Not enough participants'
	else:
		return sorted(((-win_num(s, w), s) for (s, w) in zip(st.split(','), we)))[n - 1][1]


DELTA = ord('a') - 1

def sumName(name):
	return sum((ord(c) - DELTA for c in name)) + len(name)

def rank(st, we, n):
	return 'No participants' if st == '' else 'Not enough participants' if n > st.count(',') + 1 else sorted(((-sumName(name.lower()) * w, name) for (name, w) in zip(st.split(','), we)))[n - 1][1]


def rank(st, we, n):
	if not st:
		return 'No participants'
	st = st.split(',')
	calc = lambda x: we[x[0]] * (len(x[1]) + sum((ord(m) - ord('a') + 1 for m in x[1].lower())))
	return sorted(sorted([m for m in enumerate(st)], key=lambda x: x[1]), key=lambda m: calc(m), reverse=True)[n - 1][1] if len(st) >= n else 'Not enough participants'


from string import ascii_lowercase

def rank(st, we, n):
	names = st.split(',')
	ranks = {}
	if st == '':
		return 'No participants'
	if n > len(names):
		return 'Not enough participants'
	for (index, name) in enumerate(names):
		som = len(name) + sum([ascii_lowercase.index(letter) + 1 for letter in name.lower()])
		ranks[name] = we[index] * som
	sort = sorted(list(ranks.items()), key=lambda x: (-x[1], x[0]))
	return [name for (name, som) in sort][n - 1]


from typing import List

def rank(st: str, we: List[int], n: int):
	if not st:
		return 'No participants'
	names = st.split(',')
	if n > len(names):
		return 'Not enough participants'
	return sorted(((-w * (len(s) + sum((ord(c) - 96 for c in s.lower()))), s) for (s, w) in zip(names, we)))[n - 1][1]


def weight_words(nam):
	sum = 0
	for x in nam:
		sum += ord(x) - 96
	return sum + len(nam)

def rank(st, we, n):
	index = 0
	if len(st) == 0:
		return 'No participants'
	lst_st = st.split(',')
	if n > len(lst_st):
		return 'Not enough participants'
	res = []
	for (name, w) in zip(lst_st, we):
		res.append((weight_words(name.lower()) * w, name))
	res = sorted(res, reverse=True)
	while index < len(res) - 1:
		tmp = res[index]
		tmp_next = res[index + 1]
		if tmp[0] == tmp_next[0]:
			if tmp[1] > tmp_next[1]:
				(res[index], res[index + 1]) = (res[index + 1], res[index])
			else:
				index = index + 1
		else:
			index = index + 1
	return res[n - 1][1]


def rank(st, we, n):
	if not st:
		return 'No participants'
	names = st.split(',')
	if len(names) < n:
		return 'Not enough participants'
	result = {names[i]: (sum((ord(l.lower()) - ord('a') + 1 for l in names[i])) + len(names[i])) * we[i] for i in range(len(names))}
	result = {k: v for (k, v) in sorted(result.items(), key=lambda item: item[0])}
	result = sorted(result.items(), key=lambda item: item[1], reverse=True)
	return result[n - 1][0]


from string import ascii_lowercase

def rank(st, we, n):
	if not st:
		return 'No participants'
	if n > len(st.split(',')):
		return 'Not enough participants'
	x = ascii_lowercase
	s = 0
	winning_num = []
	names = []
	group = sorted(list(zip(st.split(','), we)))
	for (name, weight) in group:
		names.append(name)
		for letter in name.lower():
			s += x.index(letter) + 1
		s += len(name)
		winning_num.append(s * weight)
		s = 0
	final = list(zip(winning_num, names))
	final.sort(reverse=True)
	z = []
	final_names = []
	for (V, N) in final:
		final_names.append(N)
		if V == final[n - 1][0]:
			z.append(N)
	z.sort()
	ind = []
	for p in z:
		ind.append(final_names.index(p))
	new_list = final_names[:min(ind)] + z + final_names[max(ind) + 1:]
	return new_list[n - 1]


def rank(st: str, we: list, n: int):
	if not st:
		return 'No participants'
	elif n > len(st.split(',')):
		return 'Not enough participants'

	def to_number(word):
		return sum((ord(c.lower()) - 96 for c in word)) + len(word)
	d = {}
	for (w, wt) in zip(st.split(','), we):
		d[w] = to_number(w) * wt
	sorted_d = sorted(d.items(), key=lambda kv: (-kv[1], kv[0]))
	print(sorted_d)
	return sorted_d[n - 1][0]