You get a "text" and have to shift the vowels by "n" positions to the right.
(Negative value for n should shift to the left.)
"Position" means the vowel's position if taken as one item in a list of all vowels within the string.
A shift by 1 would mean, that every vowel shifts to the place of the next vowel.
Shifting over the edges of the text should continue at the other edge.

Example:

text = "This is a test!"
n = 1
output = "Thes is i tast!"

text = "This is a test!"
n = 3
output = "This as e tist!"

If text is null or empty return exactly this value.
Vowels are "a,e,i,o,u".



Have fun coding it and please don't forget to vote and rank this kata! :-)

I have created other katas. Have a look if you like coding and challenges.

Difficulty: introductory

Starter code:

def vowel_shift(text, n):
	

Solutions:
import re
from collections import deque

def vowel_shift(text,n):
    try:
        tokens = re.split(r'([aeiouAEIOU])', text)
        if len(tokens) > 1:
            vowels = deque(tokens[1::2])
            vowels.rotate(n)
            tokens[1::2] = vowels
        return ''.join(tokens)
    except TypeError:
        return None

def vowel_shift(text,n):
    if text in (None, ""):
        return text
        
    vwl = [x for x in text if x in "aeiouAEIOU"]
    
    if len(vwl) == 0:
        return text

    n %= len(vwl)
    vwl = list(vwl[-n:] + vwl[:-n])

    return "".join([x if x not in "aeiouAEIOU" else vwl.pop(0) for x in text])

import re
def vowel_shift(text,n):
    if not text: return text
    vowels = [v for v in text if v in 'aeiouAEIOU']
    n = n % len(vowels) if len(vowels) else n
    shifted_vowels = vowels[-n:] + vowels[:-n]
    return re.sub('[aeiouAEIOU]', lambda _: shifted_vowels.pop(0), text)

import re
def vowel_shift(s,n):
    vow = re.sub(r'[^aeiouAEIOU]',"",s or "")
    if not s or n == 0 or not vow: return s
    n %= len(vow)
    vow = iter(vow[-n:] + vow[:-n])
    return "".join(i if i not in "aeiouAEIOU" else next(vow) for i in s)

is_vowel = lambda c: c in "aeiouAEIOU"

def vowel_shift(text, n):
    if not text or not n:
        return text
    vowels = [c for c in text if is_vowel(c)]
    n = -n % (len(vowels) or 1)
    vowels = iter(vowels[n:] + vowels[:n])
    return "".join(c if not is_vowel(c) else next(vowels) for c in text)


from itertools import chain
vowel = set("aeiouAEIOU").__contains__

def vowel_shift(text, n):
    if not (text and n): return text
    L = list(filter(vowel, text))
    if not L: return text
    n %= len(L)
    it = chain(L[-n:], L[:-n])
    return ''.join(next(it) if vowel(c) else c for c in text)

from itertools import cycle, islice

def vowel_shift(text, n):
    chrs = [c for c in text or '' if c.lower() in 'aeiou']
    if text and chrs:
        it = islice(cycle(chrs), -n % len(chrs), None)
        text = ''.join(next(it) if c.lower() in 'aeiou' else c for c in text)
    return text

import re

def vowel_shift(text, n):
    if not text:
        return text
    vowels = [c for c in text if c in "AEIOUaeiou"]
    if not vowels:
        return text
    vowels = iter(vowels[-n % len(vowels):] + vowels)
    return re.sub('[AEIOUaeiou]', lambda m: next(vowels), text)

from re import split
def vowel_shift(text, n):
    if text == None:
        return None
    parts = split(r"([aeiouAEIOU])", text)
    return "".join(parts[i if i % 2 == 0 else (i - 2*n) % (len(parts) - 1)] for i in range(len(parts)))

def vowel_shift(text, n):
    if text is None or text is '':
        return text
    text = [n for n in text]
    vowels = []
    for x in range(len(text)):
        if text[x].lower() in 'aeuoi':
            vowels.append(text[x])
            text[x] = None
    if len(vowels) == 0:
        return ''.join(text)
    while n != 0:
        if n > 0:
            vowels.insert(0, vowels.pop(-1))
            n -= 1
        else:
            vowels.insert(len(vowels) - 1, vowels.pop(0))
            n += 1
    while len(vowels) != 0:
        text[text.index(None)] = vowels.pop(0)
    return ''.join(text)