# Hey You !

Sort these integers for me ...

By name ...

Do it now !


---

## Input

* Range is ```0```-```999```

* There may be duplicates

* The array may be empty

## Example

* Input: 1, 2, 3, 4
* Equivalent names: "one", "two", "three", "four"
* Sorted by name: "four", "one", "three", "two"
* Output: 4, 1, 3, 2

## Notes
* Don't pack words together:
 * e.g. 99 may be "ninety nine" or "ninety-nine"; but not "ninetynine"
 * e.g 101 may be "one hundred one" or "one hundred and one"; but not "onehundredone"
* Don't fret about formatting rules, because if rules are consistently applied it has no effect anyway:
 * e.g. "one hundred one", "one hundred two"; is same order as "one hundred **and** one", "one hundred **and** two"
 * e.g. "ninety eight", "ninety nine"; is same order as "ninety-eight", "ninety-nine"
 
```if:c
* For `C` code the input array may be NULL. The return value is freed if non-NULL.
```

Difficulty: introductory

Starter code:

def sort_by_name(arr):
	

Solutions:
def int_to_word(num):
    d = { 0 : 'zero', 1 : 'one', 2 : 'two', 3 : 'three', 4 : 'four', 5 : 'five',
          6 : 'six', 7 : 'seven', 8 : 'eight', 9 : 'nine', 10 : 'ten',
          11 : 'eleven', 12 : 'twelve', 13 : 'thirteen', 14 : 'fourteen',
          15 : 'fifteen', 16 : 'sixteen', 17 : 'seventeen', 18 : 'eighteen',
          19 : 'nineteen', 20 : 'twenty',
          30 : 'thirty', 40 : 'forty', 50 : 'fifty', 60 : 'sixty',
          70 : 'seventy', 80 : 'eighty', 90 : 'ninety' }


    assert(0 <= num)

    if (num < 20):
        return d[num]

    if (num < 100):
        if num % 10 == 0: return d[num]
        else: return d[num // 10 * 10] + '-' + d[num % 10]

    if (num < 1000):
        if num % 100 == 0: return d[num // 100] + ' hundred'
        else: return d[num // 100] + ' hundred and ' + int_to_word(num % 100)

def sort_by_name(arr):
    return sorted(arr, key=int_to_word)


S = ["", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
     "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"]
TENTH = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]


def convertToString(n):
    if not n: return "zero"
    c,t,u = map(lambda v: (n%(v*10))//v, (100,10,1))
    return " ".join(s for s in ["{} hundred".format(S[c]) * bool(c), TENTH[t], S[u+10*(t==1)]] if s)

def sort_by_name(arr): return sorted(arr, key=convertToString)

def sort_by_name(arr):
    return sorted(arr, key=convert)

def convert(a):
    if not a: return "zero"
    d = {1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten', 11:'eleven', 12:'twelve', 13:'thirteen', 14:'fourteen', 15:'fifteen', 16:'sixteen', 17:'seventeen', 18:'eighteen', 19:'nineteen', 20:'twenty', 30:'thirty', 40:'forty', 50:'fifty', 60:'sixty', 70:'seventy', 80:'eighty', 90:'ninety'}
    r = []
    if a // 100: r.append("{} hundred".format(d[a // 100]))
    if a % 100:
        if a % 100 <= 20: r.append(d[a % 100])
        else:
            b = d[a % 100 // 10 * 10]
            if a % 10: b += " {}".format(d[a % 10])
            r.append(b)
    return " ".join(r)

ones = {'0': 'zero', '1': 'one', '2': 'two', '3': 'three', '4': 'four',
        '5': 'five', '6': 'six','7': 'seven', '8': 'eight', '9': 'nine' }

teens = {'11': 'eleven', '12': 'twelve', '13': 'thirteen', '14': 'fourteen',
         '15': 'fifteen', '16': 'sixteen', '17': 'seventeen', 
         '18': 'eighteen', '19': 'nineteen' }

tens = { '1': 'ten', '2': 'twenty', '3': 'thirty', '4': 'forty', 
         '5': 'fifty', '6': 'sixty', '7': 'seventy', '8': 'eighty', 
         '9': 'ninety' }

hundreds = {'100' : 'one hundred', '200' : 'two hundred',
            '300' : 'three hundred', '400' : 'four hundred',
            '500' : 'five hundred', '600' : 'six hundred',
            '700' : 'seven hundred', '800' : 'eight hundred',
            '900' : 'nine hundred'}

def num_to_word(n):

    str_num = str(n)

    if n >= 100:
        first_digit = str_num[0] + '00'
        second_digit = str_num[1]
        third_digit = str_num[2]
    elif n > 9:
        first_digit = str_num[0]
        second_digit = str_num[1]
    else:
        return ones[str_num]


    if n > 99:
        if second_digit == '0' and third_digit != '0':
            return '{} {}'.format(hundreds[first_digit], ones[third_digit])
        elif second_digit != '0' and third_digit == '0':
            return '{} {}'.format(hundreds[first_digit], tens[second_digit])
        elif int(second_digit + third_digit) > 10 and int(second_digit + third_digit) < 20:
            return '{} {}'.format(hundreds[first_digit], teens[second_digit + third_digit])
        elif third_digit != '0':
            return '{} {}-{}'.format(hundreds[first_digit], tens[second_digit], ones[third_digit])
        else:
            return hundreds[str_num]
            
    else:
        if n > 10 and n < 20:
            return teens[str_num]
        elif second_digit != '0':
            return '{}-{}'.format(tens[first_digit], ones[second_digit])
        else:
            return tens[first_digit]

int_to_word = {_ : num_to_word(_) for _ in range(1000)}                             
word_to_int = {num_to_word(_) : _ for _ in range(1000)} 

def sort_by_name(arr):
    return [word_to_int[word] for word in sorted(int_to_word[num] for num in arr)]


S     = " one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen".split(" ")
TENTH = "  twenty thirty forty fifty sixty seventy eighty ninety".split(" ")        # Empty strings wanted at the beginning, when splitting!

def convertToString(n):
    if not n: return "zero"
    c,t,u = map(int, f'{n:0>3}')
    return " ".join(s for s in [f'{S[c]} hundred' * bool(c), TENTH[t], S[u+10*(t==1)]] if s)

def sort_by_name(arr): return sorted(arr, key=convertToString)

num2words1 = {0: 'zero', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'thirteen', 14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 17: 'seventeen', 18: 'eighteen', 19: 'nineteen'}
num2words2 = ['','','twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
def sort_by_name(arr):
    return sorted(arr, key=lambda x: words(x))
def words(n):
    res=[]
    if n>=100:
        res.append(num2words1[n//100])
        res.append("hundred")
        n-=n//100*100
    if n>=20:
        res.append(num2words2[n//10])
        n-=n//10*10
    if n>0:
        res.append(num2words1[n])
    if not res:
        res.append("zero")
    return " ".join(res)

words = "zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty thirty forty fifty sixty seventy eighty ninety"
words = words.split(" ")

def num2word(n):
    if n < 20:
        return words[n]
    elif n < 100:
        return words[18 + n // 10] + ('' if n % 10 == 0 else '-' + words[n % 10])
    else:
        return num2word(n // 100) + " hundred" + (' ' + num2word(n % 100) if n % 100 > 0 else '')

def sort_by_name(arr):
    return sorted(arr, key=num2word)

def sort_by_name(arr):
    comparing_list, before_sort_dict, resulty_list = [], {}, []
    nu_dict = {'0': '', '1': 'one', '2': 'two', '3': 'three', '4': 'four', '5': 'five', '6': 'six', '7': 'seven',
                '8': 'eight', '9': 'nine', '10': 'ten', '11': 'eleven', '12': 'twelve', '13': 'thirteen',
               '14': 'fourteen', '15': 'fifteen', '16': 'sixteen', '17': 'seventeen', '18': 'eighteen',
               '19': 'nineteen'}
    for number in map(str, arr):
        if len(number) == 3:
            if 10 <= int(number[1:]) < 20:
                temp_word = number[1] + number[2]
                numberly_str = '{hundreds} hundred {tens}'.format(hundreds=nu_dict[number[0]], tens=nu_dict[temp_word])
            else:
                numberly_str = '{hundreds} hundred {tens}ty {deci}'.format(hundreds=nu_dict[number[0]],
                                                                tens=nu_dict[number[1]], deci=nu_dict[number[2]])
        elif len(number) == 2:
            if 10 <= int(number) < 20:
                temp_word = number[0] + number[1]
                numberly_str = '{tens}'.format(tens=nu_dict[temp_word])
            else:
                numberly_str = '{tens}ty {deci}'.format(tens=nu_dict[number[0]], deci=nu_dict[number[1]])
        else:
            if number == '0':
                numberly_str = 'zero'
            else:
                numberly_str = '{deci}'.format(deci=nu_dict[number[0]])
        temp_list = numberly_str.split()
        for pos, word in enumerate(temp_list):
            if word == 'ty':
                temp_list[pos] = ''
        numberly_str = ' '.join(temp_list)
        numberly_str = numberly_str.replace('  ', ' ').replace('fourty', 'forty').replace('twoty', 'twenty')
        numberly_str = numberly_str.replace('threety', 'thirty').replace('fivety', 'fifty').replace('eightty', 'eighty')
        numberly_str = numberly_str.rstrip()
        comparing_list.append(numberly_str)
    for index, crypt in enumerate(comparing_list):
        before_sort_dict[index] = crypt
    sorted_dict = {k: v for k, v in sorted(before_sort_dict.items(), key=lambda item: item[1])}
    for key, value in sorted_dict.items():
        resulty_list.append(arr[key])
    return resulty_list

def sort_by_name(arr):
    num_dict = {
    1:'one', 2:'two', 3:'three', 4:'four', 5:'five',
    6:'six', 7:'seven', 8:'eight', 9:'nine', 10:'ten',
    11:'eleven', 12:'twelve', 13:'therteen', 14:'fourteen',
    15:'fifteen', 16:'sixteen', 17:'seventeen', 18:'eighteen',
    19:'nineteen', 20:'twenty', 30:'thirty', 40:'forty',
    50:'fifty', 60:'sixty', 70:'seventy', 80:'eighty',
    90:'ninety', 0:'zero', -1:'', -10:''
    }
    raw_list = [] # will be tuple [('two', 2), ('zero', 0)]
    for i in arr:
        if i in num_dict:
            raw_list.append(tuple([num_dict[i], i]))
        else:
            raw_i = str(i)
            nums = len(raw_i)
            if nums == 2:
                j = int(raw_i[1])
                if 10 < i < 20:
                    raw_list.append(tuple([num_dict[i], i]))
                    continue
                if j != 0:
                    raw_list.append(tuple(['{} {}'.format(num_dict[int(raw_i[0])*10],
                    num_dict[int(raw_i[1])]), i]))
                    continue
                else:
                    raw_list.append(tuple(['{}'.format(num_dict[int(raw_i[0])*10]), i]))
                    continue
            else:
                z = int(raw_i[1])
                k = int(raw_i[2])
                if z == 0:
                    z = -1
                if k == 0:
                    k = -1
                if 10 < int(raw_i[1]+raw_i[2]) < 20:
                    raw_list.append(tuple(['{} hundred {}'.format(num_dict[int(raw_i[0])],
                    num_dict[int(raw_i[1]+raw_i[2])]).replace("  ", ' '), i]))
                    continue
                raw_list.append(tuple(['{} hundred {} {}'.format(num_dict[int(raw_i[0])],
                num_dict[z*10], num_dict[k]).replace("  ", ' '), i]))
    raw_list.sort(key = lambda x: x[0])
    # raw_list.sort(key = lambda x: (x[0], x[1]))
    out_list = []
    for i in raw_list:
        out_list.append(i[1])
    return out_list

from enum import Enum
class Numbers(Enum):
    zero = 0
    one = 1
    two = 2
    three = 3
    four = 4
    five = 5
    six = 6
    seven = 7
    eight = 8
    nine = 9
    ten = 10
    eleven = 11
    twelve = 12
    thirteen = 13
    fourteen = 14
    fifteen = 15
    sixteen = 16
    seventeen = 17
    eighteen = 18
    nineteen = 19
    twenty = 20
    thirty = 30
    forty = 40
    fifty = 50
    sixty = 60
    seventy = 70
    eighty = 80
    ninety = 90


def number_to_name(number):
    return Numbers(number).name if number < 20 else Numbers(number).name if number < 100 and not number % 10 else (f"{Numbers(number // 10 * 10).name}-{Numbers(number % 10).name}" if number < 100 else f"{Numbers(number // 100).name} hundred" if not number % 100 else f"{Numbers(number // 100).name} hundred and {number_to_name(number % 100)}")
    
def sort_by_name(arr):
    return sorted(arr,key=number_to_name)