In this kata, you will make a function that converts between `camelCase`, `snake_case`, and `kebab-case`.

You must write a function that changes to a given case. It must be able to handle all three case types:

```python
py> change_case("snakeCase", "snake")
"snake_case"
py> change_case("some-lisp-name", "camel")
"someLispName"
py> change_case("map_to_all", "kebab")
"map-to-all"
py> change_case("doHTMLRequest", "kebab")
"do-h-t-m-l-request"
py> change_case("invalid-inPut_bad", "kebab")
None
py> change_case("valid-input", "huh???")
None
py> change_case("", "camel")
""
```

Your function must deal with invalid input as shown, though it will only be passed strings. Furthermore, all valid identifiers will be lowercase except when necessary, in other words on word boundaries in `camelCase`.

_**(Any translations would be greatly appreciated!)**_

Difficulty: introductory

Starter code:

def change_case(identifier, targetCase):
	

Solutions:
import re

def change_case(label, target):
    if ('_' in label) + ('-' in label) + (label != label.lower()) > 1:
        return
    
    if target == 'snake':
        return re.sub('([A-Z])', r'_\1', label.replace('-', '_')).lower()
    
    if target == 'kebab':
        return re.sub('([A-Z])', r'-\1', label.replace('_', '-')).lower()
    
    if target == 'camel':
        return re.sub('([_-])([a-z])', lambda m: m.group(2).upper(), label)

def change_case(label, case):
    if case not in ['snake', 'kebab', 'camel'] or ('_' in label) + ('-' in label) + (label != label.lower()) > 1:
        return
    
    return ''.join( '_' + c.lower() if c.isupper()  and case == 'snake' else
                    '_' if c == '-'                 and case == 'snake' else
                    
                    '-' + c.lower() if c.isupper()  and case == 'kebab' else
                    '-' if c == '_'                 and case == 'kebab' else
                    
                    c.upper() if label[i-1] in '-_' and case == 'camel' else
                    '' if c in '-_'                 and case == 'camel' else
                    
                    c for i, c in enumerate(label) )

import re

CHANGES     = {'kebab': '-', 'camel': '', 'snake': '_'}
VALID_CASE  = re.compile(r'[A-Z_-]')
CHANGE_CASE = re.compile(r'[_-][a-z]|[A-Z]')


def change_case(s, targetCase):

    def convertCase(m):
        return (str.upper if targetCase=='camel' else str.lower)(CHANGES[targetCase] + m.group()[-1])
    
    if targetCase in CHANGES and len({'A' if c.isalpha() else c for c in VALID_CASE.findall(s)}) <= 1:
        return CHANGE_CASE.sub(convertCase, s)


import re

def change_case(s, case):
    
    actions = {
        'snake': lambda s: re.sub(r'([A-Z\-])', r'_\1', s).lower().replace('-', ''),
        'camel': lambda s: re.sub(r'(\-|_)(.)', lambda x: x[2].upper(), s),
        'kebab': lambda s: re.sub(r'([A-Z_])', r'-\1', s).lower().replace('_', '')
    }
    return s if not s else sum((any(x.isupper() for x in s), '_' in s, '-' in s)) < 2 \
                                       and actions.get(case, lambda s: None)(s) or None

def change_case(id, t):
    q = ('_' in id) + ('-' in id) + any(x.isupper() for x in set(id))
    if q > 1: return
    d = {'kebab': '-', 'snake': '_'}
    l, index = [''], 0
    for x in id:
        if not l[index] or not x.isupper() and x.isalpha() and l[index][-1].isalpha():
            l[index] += x
        elif x.isalpha():
            l.append(x)
            index += 1
        else:
            l.append('')
            index += 1

    if t in d:
        return f'{d[t]}'.join(x.lower() for x in l)
    if t == 'camel':
        return ''.join(w.capitalize() if i else w for i,w in enumerate(l))

def change_case(identifier, targetCase):
# kebab make dashes after all capital, snake underscore after capital
# camel makes kebab to caps
#account for 
    if isBad(identifier):
        return None
    if targetCase == 'snake':
        return snake(identifier)
    elif targetCase == 'camel':
        return camel(identifier)
    elif targetCase == 'kebab':
        return kebab(identifier)
    return None
    
def snake(myString):
    newString = myString
    for i in range (0, len(myString)):
        if ord(myString[i]) >= ord('A') and ord(myString[i]) <= ord('Z'):
            #means it is caps
            pos = newString.index(myString[i:])
            newString = newString[:pos] + '_' + newString[pos].lower() + newString [pos + 1:]
        elif myString[i] == '-':
            pos = newString.index(myString[i:])
            #newSting = 
            newString = newString[:pos] + '_' + newString[pos + 1:]
    return newString.lower()
    
def kebab(myString):
    newString = myString
    for i in range (0, len(myString)):
        if ord(myString[i]) > ord('A') -1 and ord(myString[i]) < ord('Z') +1:
                #means it is caps
            pos = newString.index(myString[i:])
            newString = newString[:pos] + '-' + newString[pos].lower() + newString [pos + 1:]

        if myString[i] == '_':
            pos = newString.index(myString[i:])
            #newSting = 
            newString = newString[:pos] + '-' + newString[pos + 1:]
        #means it is underscore
    return newString.lower()
    
def camel(myString):
    #why doesnt this work
    if len(myString) ==0:
        return myString
    myString = myString.replace('-', '_')
    newString = myString.split('_')
    for i in range (0, len(newString)):
        if i != 0:
            newString[i] = newString[i][0].upper() + newString[i][1:]
    return "".join(newString)   
   #
def isBad(myString):    
    if '_' in myString and '-' in myString:
        return True
    if '--' in myString or '__' in myString:
        return True
    if not myString.lower() == myString and '_' in myString:
        return True
    if not myString.lower() == myString and '-' in myString:
        return True
    return False

import re

# TODO: need to refactor later :)
find_snake = re.compile("([_])([A-Za-z])")
find_camel = re.compile("([A-Z])")
find_kebab = re.compile("([-])([A-Za-z])")

is_camel = lambda x: x != x.lower()
is_snake = lambda x: '_' in x
is_kebab = lambda x: '-' in x

def to_camel(match):
    return match.group(2).upper()

def to_snake(match):
    return '_' + match.group(1).lower()
    
def to_kebab(match):
    return '-' + match.group(1).lower()

def change_case(text, target):
    if text == '':
        return ''
    if target not in ['camel','kebab','snake'] \
    or sum([is_camel(text), is_snake(text), is_kebab(text)]) != 1:
        return None
    if is_camel(text):
        if target == 'snake':
            return re.sub(find_camel, to_snake, text).lower()
        elif target == 'kebab':
            return re.sub(find_camel, to_kebab, text).lower()
    elif is_snake(text):
        if target == 'camel':
            return re.sub(find_snake, to_camel, text)
        elif target == 'kebab':
            return text.replace('_', '-').lower()
    elif is_kebab(text):
        if target == 'snake':
            return text.replace('-', '_').lower()
        elif target == 'camel':
            return re.sub(find_kebab, to_camel, text)
    return text

def discover_case(identifier):
    if identifier is None:
        return None
    elif identifier == '':
        return ''
    elif is_camel(identifier):
        return 'camel'
    elif is_snake(identifier):
        return 'snake'
    elif is_kebab(identifier):
        return 'kebab'
    return None

def is_camel(identifier):
    found_uppercase = False
    
    for index, ch in enumerate(identifier):
        if not ch.isalnum():
            return False
        elif index != 0 and ch.isalpha() and ch.isupper():
            found_uppercase = True
            
    return found_uppercase

def is_snake(identifier):
    for ch in identifier:
        if ch.isupper():
            return False
            
    return '_' in identifier and '-' not in identifier

def is_kebab(identifier):
    for ch in identifier:
        if ch.isupper():
            return False
            
    return '-' in identifier and '_' not in identifier

def split_words(identifier, case):
    if case == 'camel':
        words = []
        word = ''
        
        for ch in identifier:
            if ch.isupper():
                words.append(word.lower())
                word = ch
            else:
                word += ch
                
        words.append(word.lower())
        return words
    elif case == 'snake':
        return identifier.split('_')
    elif case == 'kebab':
        return identifier.split('-')
    else:
        return None

def to_camel(words):
    result = ''
    for index, word in enumerate(words):
        if index == 0:
            result += word
        else:
            result += word.capitalize()
    return result

def to_snake(words):
    return '_'.join(words)

def to_kebab(words):
    return '-'.join(words)

def change_case(identifier, targetCase):
    case = discover_case(identifier)
    if not case:
        return case
        
    words = split_words(identifier, case)
    if not words:
        return None
    
    if targetCase == 'camel':
        return to_camel(words)
    elif targetCase == 'snake':
        return to_snake(words)
    elif targetCase == 'kebab':
        return to_kebab(words)
    else:
        return None


def change_case(identifier, targetCase):
    id = list(str(identifier))
    conv = []
    
    if identifier.islower() == False and (id.count('-') != 0 or id.count('_') != 0) == True: #checks if there are upper case and hyphens or underscores
        return None
    
    if id.count('-') != 0 and id.count('_') != 0:
        return None
    
    if targetCase == 'snake':
        return change_snake(id, conv)
        
    if targetCase == 'camel':
        return change_camel(id, conv)
    
    if targetCase == 'kebab':
        return change_kebab(id, conv)
    
    else:
         return None
        
def change_snake(id, conv): #converts Capital to _lower  
    for i in id:
        if i.isupper() == True:
            conv.append('_' + i.lower())
            #conv.append(i.lower())
        
        elif i == '-':
            conv.append('_')
            
        else:
            conv.append(i)
    
    return ''.join(conv)
    
def change_camel(id, conv): #converts -lower to Capital
    ids = id.copy()
    ids.insert(0, '.')
    n = 0
    
    for i in id:       
        n = n+1
        
        if i == '-' or i == '_':     
            continue   
            
        if ids[n-1] == '-' or ids[n-1] == '_':
            
            conv.append(i.upper())
              
        else:
            conv.append(i)
               
        
    return ''.join(conv)
    
def change_kebab(id, conv): #converts 
    for i in id:
        if i == '_':
            conv.append('-')
            continue
            
        if i.isupper() == True:
            conv.append('-' + i.lower())
        
        else:
            conv.append(i)
        
    return ''.join(conv)

import re

def is_snake_case(identifier):
    return bool( re.fullmatch(r'[a-z_]+', identifier) )

def is_camel_case(identifier):
    return bool(re.fullmatch(r'([a-z]+[A-Z])+[a-z]*', identifier))

def is_kebab_case(identifier):
    return bool(re.fullmatch(r'[a-z]*-?', identifier))
  
def is_mixed_case(identifier):
    if "-" in identifier and "_" in identifier:
        return True
    elif "-" in identifier and [c for c in identifier if c.isupper()]:
        return True
    elif "_" in identifier and [c for c in identifier if c.isupper()]:
        return True
                
def change_case(identifier, targetCase):
    # if identifier is empty
    if not identifier:
        return ""
    
    # if targetCase is invalid
    elif targetCase not in ['kebab', 'camel', 'snake']:
        return None
    
    # if identifier is mixed case
    elif is_mixed_case(identifier):
        return None
    
    # change case to snake case
    elif targetCase == "snake" and not is_snake_case(identifier):
        split = [char for char in re.split(r'([A-Z]|-)', identifier) if char]
        for i, char in enumerate(split):
            if char.isupper():
                split[i] = '_' + char.lower()
            elif char == "-":
                split[i] = "_"
        return ''.join(split)
    
    # change case to camel case
    elif targetCase == "camel" and not is_camel_case(identifier):    
        split = re.split(r'[_-]', identifier)
        return split[0] + ''.join(word.title() for word in split[1:])
        
    # change case to kebab case
    elif targetCase == "kebab" and not is_kebab_case(identifier):
        split = re.split(r'([A-Z]|_)', identifier)
        kebab = split[0]
        for i, word in enumerate(split[1:]):
            if not word or word == "_":
                kebab += "-"
            elif word.isupper():
                if kebab[-1] == "-":                    
                    kebab += word.lower()
                else:
                    kebab += '-' + word.lower()
            else:
                kebab += word.lower()
        return kebab
    
    # identifier and targetCase already match
    else:
        return identifier