You wrote all your unit test names in camelCase.
But some of your colleagues have troubles reading these long test names.
So you make a compromise to switch to underscore separation.

To make these changes fast you wrote a class to translate a camelCase name
into an underscore separated name.

Implement the ToUnderscore() method.

Example:

`"ThisIsAUnitTest" => "This_Is_A_Unit_Test"`


**But of course there are always special cases...**

You also have some calculation tests. Make sure the results don't get split by underscores.
So only add an underscore in front of the first number.

Also Some people already used underscore names in their tests. You don't want to change them.
But if they are not split correct you should adjust them.

Some of your colleagues mark their tests with a leading and trailing underscore.
Don't remove this.

And of course you should handle empty strings to avoid unnecessary errors. Just return an empty string then.

Example:

`"Calculate15Plus5Equals20" => "Calculate_15_Plus_5_Equals_20"`

`"This_Is_Already_Split_Correct" => "This_Is_Already_Split_Correct"`

`"ThisIs_Not_SplitCorrect" => "This_Is_Not_Split_Correct"`

`"_UnderscoreMarked_Test_Name_" => _Underscore_Marked_Test_Name_"`

Difficulty: introductory

Starter code:

def toUnderScore(name):
	

Solutions:
import re

def toUnderScore(name):
    return re.sub("(?<=[^_-])_?(?=[A-Z])|(?<=[^\\d_])_?(?=\\d)", "_" , name)

from re import sub

def toUnderScore(name):
    return sub('([a-zA-Z](?=[A-Z0-9])|\d(?=[A-Z]))', r'\1_', name)

def toUnderScore(name):
    if len(name) ==0:
        return ""
    hold=[]
    for x in name:
        hold.append(x)
    for index, elem in enumerate(hold):
        if index !=0:
            test = hold[index-1]
            if elem.isupper() and test != "_":
                hold.insert(index, "_")
            if elem.isdigit() and test.isalpha():
                hold.insert(index, "_")
                
    output= ''.join(hold)
    return output
    pass

import re


def toUnderScore(name):
    return re.sub(r"(?<=[^^_])([A-Z]|\d+)", r"_\1", name)

from functools import partial
from re import compile

toUnderScore = partial(compile(r"(?<=[a-zA-Z])(?=[A-Z0-9])|(?<=[0-9])(?=[A-Z])").sub, r"_")

import re

def toUnderScore(name):
    if not name: return ""
    a = '_'.join([s for s in re.split(r'(_?[A-Z][a-z]*_?|[0-9]+[a-z]*)', re.sub('_', '', name)) if s])
    if name[0] == '_': a = '_' + a
    if name[-1] == '_': a = a + '_'
    return a

def toUnderScore(s):
    return ''.join('_'+x if (x.isupper() or x.isnumeric()) and not (x.isnumeric() and s[i-1].isnumeric()) and s[i-1] != '_' and i != 0 else x for i, x in enumerate(s))


import re

def toUnderScore(name):
    return re.sub(r'(?<!^)(?<!_)(\d+|[A-Z][a-z]*)', r'_\1', name)

def toUnderScore(name):
    
    list_of_chars = []
    previous_char = None

    for char in name:

        if previous_char is not None and char != "_" and previous_char != "_":

            if char.isupper() or char.isdigit() and not previous_char.isdigit():
                list_of_chars.append("_")
            
        list_of_chars.append(char)
        previous_char = char

    return "".join(list_of_chars)

import re;toUnderScore=lambda s:re.sub(r"(?<=[^0-9])(\d+)", r"_\1", re.sub(r"(?<=[^_])([A-Z])(?=[a-z]*)", r"_\1", s[0]+s[1:-1].replace("_","")+s[-1])) if s else ""