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.

Difficulty: introductory

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())-96for 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]