Welcome

This kata is inspired by This Kata


We have a string s

We have a number n

Here is a function that takes your string, concatenates the even-indexed chars to the front, odd-indexed chars to the back.

Examples

    s = "Wow Example!"
    result = "WwEapeo xml!"
    s = "I'm JomoPipi"
    result = "ImJm ii' ooPp"
    
The Task:

return the result of the string after applying the function to it n times.

example where s = "qwertyuio" and n = 2:

    after 1 iteration  s = "qetuowryi"
    after 2 iterations s = "qtorieuwy"
    return "qtorieuwy"

 Note 

there's a lot of tests, big strings,
and n is greater than a billion

so be ready to optimize.

after doing this: do it's best friend!

# Check out my other kata!

        
Matrix Diagonal Sort OMG
String -> N iterations -> String
String -> X iterations -> String
ANTISTRING
Array - squareUp b!
Matrix - squareUp b!
Infinitely Nested Radical Expressions
pipi Numbers!

Difficulty: introductory

Starter code:

def jumbled_string(s, n):
	

Solutions:
def jumbled_string(s, n):
    iterations = [s]
    
    while True:
        s = s[::2] + s[1::2]
        if s == iterations[0]: break
        iterations.append(s)
    
    return iterations[n % len(iterations)]

#Kata: String -> N iterations -> String  Rating 5kyu


#To optimize this problem, we must look at the circular (modular) nature of the iterations
#of the even/odd rule.  Given any string, under the even/odd rule, the number of permutations
#will be no longer than the length of the original message.  
# e.g. 'abcdefghijklmnop' has only four unique permutations under the even/odd rule:
#      ['abcdefghijklmnop', 'acegikmobdfhjlnp', 'aeimbfjncgkodhlp', 'aibjckdlemfngohp']
# So, if we want to apply the even/odd rule N times for string 'abcdefghijklmnop', we need but
# access the 'N modulo n' element in the permutation list (where m is the length of permutation list)


def buildPermList(originalMsg):
    
    listPerms = []
    listPerms.append(originalMsg)   #index 0 is original message
    curMsg = originalMsg
    
    while True:
        even = curMsg[0::2]
        odd = curMsg[1::2]
        curMsg = even+odd
        if curMsg != originalMsg:   #Scenario: Back to the original message
            listPerms.append(curMsg)
        else:
            break

    #listPerms is <= the length of the origianl message; ith element is the ith permutation under
    # the even/odd rules
    return listPerms    
#-----end function


def jumbled_string(msg, n):

    permList = buildPermList(msg)
    numUniquePerms = len(permList)
    desiredRotIndex = n % numUniquePerms

    return permList[desiredRotIndex]

#-----end function


#Demonstrative test code
# msg = 'abcdefghijklmnop'
# n=18
# myList = buildPermList(msg)
# print("---Length of list: ", len(myList))
# print("---List: ", myList)
# lenList = len(myList)
# desiredIndex = n % lenList
# print( "The location: ", str(desiredIndex) )
# print( "Desired String",  rotationsByN(msg, n) )


def jumbled_string(s, n):
    seen = []
    while s not in seen:
        seen.append(s)
        s = f"{s[::2]}{s[1::2]}"
    return seen[n % len(seen)]

def jumbled_string(s, n):
    ml = ['bullshit']
    new_str = s

    while s != ml[-1]:
        new_str = new_str[::2] + new_str[1::2]
        ml.append(new_str)
    return ml[n% (len(ml)-1)]

def jumbled_string(s, n):
    mixer = lambda s: s[::2] + s[1::2]
    
    if n == 1: return mixer(s) 
    
    # Count max possible iterations
    cnt = 1
    x = s
    while s != mixer(x):
        cnt += 1
        x = mixer(x)
            
    # Calculate needed amount of iterations         
    max = n % cnt
    while max != 0:
        s = mixer(s)
        max -= 1
    return s

def jumbled_string(s, n):
    results = [s]
    while n:
        s = s[::2] + s[1::2]
        n -= 1
        if s == results[0]:
            return results[n % len(results)]
        else:
            results.append(s)
    return s

def jumbled_string(s, n):
   a = s
   i = 0
   while i < n:            # Find the period of string after which it's the same
      s = s[::2] + s[1::2]
      i += 1
      if s == a:
         break
   n = n % i
   for i in range(n):
      s = s[::2] + s[1::2]
   return s

def jumbled_string(s, n):
    idx  = list(range(0,len(s),2)) + list(range(1,len(s),2))
    lst = []
    while not lst or s != lst[0]:
        lst.append(s)
        s = ''.join(s[i] for i in idx)
        if len(lst) == n: return s
    return lst[ n%len(lst) ]

def jumbled_string(s, n):
    combine = lambda s : s[0::2] + s[1::2]
    for _ in range(n%multiplicativeOrder(2, len(s))):
        s = combine(s)
    return s

def GCD (a, b ) : 
    if (b == 0 ) : 
        return a 
    return GCD( b, a % b ) 

def multiplicativeOrder(A, N) : 
    if (GCD(A, N ) != 1) : 
        return multiplicativeOrder(A, N-1)
    result = 1

    K = 1
    while (K < N) : 
        result = (result * A) % N 
        if (result == 1) : 
            return K 
        K = K + 1
    return -1



"""
l = length of string
m = l (if l is odd) or l - 1 (if l is even)
k = length of a cycle to get back to original string
then (2^k) mod m = 1
"""
# find minimum k where (b ^ k) % m = 1 and k > 0
def multiplicativeOrder(b, m):
    k, r = 1, 1
    while True:
        r = (r * b) % m
        if r == 1:
            return k
        k += 1

def jumbled_string(s, n):
    l = len(s)
    m = l if l & 1 else l - 1
    k = multiplicativeOrder(2, m)
    answer = s
    for i in range(n % k):
        answer = answer[::2] + answer[1::2]
    return answer