This kata is  blatantly copied from  inspired by This Kata
Welcome

this is the second in the series of the string iterations kata!

Here we go!

---------------------------------------------------------------------------------

We have a string s

Let's say you start with this: "String"

The first thing you do is reverse it: "gnirtS"

Then you will take the string from the 1st position and reverse it again: "gStrin"

Then you will take the string from the 2nd position and reverse it again: "gSnirt"

Then you will take the string from the 3rd position and reverse it again: "gSntri"

Continue this pattern until you have done every single position, and then you will return the string you have created. For this particular string, you would return: 
"gSntir"

now,

The Task:

In this kata, we also have a number x

take that reversal function, and apply it to the string x times.


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

    example where s = "String" and x = 3:

    after 0 iteration  s = "String"
    after 1 iteration  s = "gSntir"
    after 2 iterations s = "rgiStn"
    after 3 iterations s = "nrtgSi"
    
    so you would return "nrtgSi".

 Note 

String lengths may exceed 2 million


x exceeds a billion


be read to optimize



if this is too hard, go here https://www.codewars.com/kata/string-%3E-n-iterations-%3E-string/java

Difficulty: MEDIUM_HARD
Starter code: def string_func(s, n):
	

Solutions:
def string_func(s, n):
	(l, s) = ([s], list(s))
	while True:
		(s[::2], s[1::2]) = (s[:len(s) // 2 - 1:-1], s[:len(s) // 2])
		l.append(''.join(s))
		if l[0] == l[-1]:
			del l[-1]
			break
	return l[n % len(l)]


def string_func(in_str, action_times):
	input_len = len(in_str)
	input_mid_point = (input_len + 1) / 2 - 1
	loops = [[0]]
	index = 0
	loop_index_is_in = [0] * input_len
	indices_not_checked = list(range(1, input_len))
	while len(indices_not_checked) != 0:
		if index < input_mid_point:
			index = index * 2 + 1
		elif index > input_mid_point:
			index = (input_len - 1 - index) * 2
		elif index == input_mid_point:
			index = input_len - 1
		if index not in indices_not_checked:
			loops.append([])
			index = indices_not_checked[0]
		loops[-1].append(index)
		indices_not_checked.remove(index)
		loop_index_is_in[index] = len(loops) - 1
	new_string = [0] * input_len
	for char_index in range(input_len):
		loop = loops[loop_index_is_in[char_index]]
		place_in_loop = loop.index(char_index)
		new_index = loop[(place_in_loop + action_times) % len(loop)]
		new_string[new_index] = in_str[char_index]
	return ''.join(new_string)


def string_func(s, x):
	if not x:
		return s
	k = [s]
	new_s = list(s)
	while True:
		(new_s[::2], new_s[1::2]) = (new_s[:len(new_s) // 2 - 1:-1], new_s[:len(new_s) // 2])
		k.append(''.join(new_s))
		if k[-1] == s:
			return k[x % (len(k) - 1)]


from itertools import chain, islice
from functools import lru_cache

def reversal_func(s):
	return ''.join(islice(chain.from_iterable(zip(s[::-1], s)), len(s)))

@lru_cache()
def period(n):
	last = 1
	for i in range(n):
		val = abs(2 * n + 1 - 2 * last)
		if val == 1:
			return i + 1
		last = val

def string_func(s, x):
	x %= period(len(s))
	for __ in range(x):
		s = reversal_func(s)
	return s


def string_func(s, n):
	(m, table) = (len(s), {})
	for i in range(m):
		if i not in table:
			(j, cycle) = (i, [])
			while i != j or not cycle:
				cycle.append(j)
				j = min(2 * j + 1, 2 * (m - j - 1))
			table.update(zip(cycle[n % len(cycle):] + cycle, cycle))
	return ''.join((s[table[i]] for i in range(m)))


def exp(permutation, n):
	result = [-1] * len(permutation)
	for i in range(len(permutation)):
		if result[i] == -1:
			(j, cycle) = (i, [])
			while True:
				cycle.append(j)
				j = permutation[j]
				if i == j:
					break
			for (j, k) in enumerate(cycle):
				result[k] = cycle[(j + n) % len(cycle)]
	return result

def string_func(s, n):
	m = len(s)
	perm = [i // 2 if i % 2 else m - 1 - i // 2 for i in range(m)]
	return ''.join((s[i] for i in exp(perm, n)))


import copy

def string_func(s, x):
	(m, l, arr, z) = (0, len(s), [0] * len(s), 0)
	while True:
		m += 1
		y = 2 ** m % (2 * l + 1)
		if y == 1 or y == 2 * l:
			break
	for i in range(1, l, 2):
		arr[z] = i
		z += 1
	for i in range(l - 2 + l % 2, -1, -2):
		arr[z] = i
		z += 1
	ss = list(s)
	x %= m
	while x > 0:
		x -= 1
		for i in range(len(arr)):
			ss[arr[i]] = s[i]
		s = ss.copy()
	return ''.join(s)


def string_func(s, x):
	len_s = len(s)
	arr = list(s)
	mapping = []
	correct_seq = list(range(len_s))
	changed_seq = correct_seq[:]
	for i in range(int(len_s / 2 + 0.5)):
		mapping.append(len_s - i - 1)
		mapping.append(i)
	if len_s % 2 != 0:
		mapping.pop()
	for div in range(1, len_s + 1):
		changed_seq = [changed_seq[i] for i in mapping]
		if changed_seq == correct_seq:
			x %= div
			break
	while x:
		arr = [arr[i] for i in mapping]
		x -= 1
	return ''.join(arr)


def string_func(s, x):
	l = len(s)
	cyc = x % life(l)
	order = list(s)
	string = list(s)
	c = 0
	for i in range(l - 1, -1 + l // 2, -1):
		order[c] = i
		c += 2
	c = 1
	for i in range(0, l // 2, 1):
		order[c] = i
		c += 2
	return ''.join(sort(order, string, cyc))

def sort(schema, string, times):
	for x in range(times):
		result = []
		for i in range(len(string)):
			result.append(string[schema[i]])
		string = result
	return string

def life(n):
	if n <= 1:
		return 1
	m = 1
	while True:
		a = 2 ** m % (2 * n + 1)
		if a == 1 or a == 2 * n:
			return m
		m = m + 1