Reputation: 20598
I am trying to create two subarrays in given order, in this case i have two integers a and b a
represents the value of the subarrays range, and b
represents how many times it needs to be rotated.
I created the subarrays like this;
def reorder(a,b):
return [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]
Imagine a
is 10 and b
is 1 the output is:
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
But how can i reverse each subarrays b
times?
The output that i want;
[[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]]
Upvotes: 1
Views: 311
Reputation: 20598
I also came up with these solutions.
With numpy's roll function;
import numpy as np
def reorder(a, b):
return [list(np.roll(v,b)) for v in [list(range(a//2)),list(range(a-a//2,a))]]
In: reorder(10,9)
Out: [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]]
Also much simpler solution with numpy's roll function;
import numpy as np
def reorder(a, b):
return np.roll(np.arange(a).reshape(2, -1), b, 1).tolist()
In: reorder(10,9)
Out: [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]]
If you don't wanna use packages and you are okay with a little bit of eye bleeding;
def reorder(a, b):
return [list(range(a//2))[-b%(a//2):] + list(range(a//2))[:-b%(a//2)], list(range(a//2, a))[-b%(a//2):] + list(range(a//2, a))[:-b%(a//2)]]
In: reorder(10,9)
Out: [[1, 2, 3, 4, 0], [6, 7, 8, 9, 5]]
Upvotes: 1
Reputation: 18106
You can rotate the inner lists by slicing:
def reorder(a,b):
slicingPosition = a/2 % b
return [y[-slicingPosition:] + y[:-slicingPosition] for y in [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]]
for x in range(1, 6):
print(x, '>>', reorder(10, x))
Output:
(1, '>>', [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
(2, '>>', [[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])
(3, '>>', [[3, 4, 0, 1, 2], [8, 9, 5, 6, 7]])
(4, '>>', [[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]])
(5, '>>', [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])
Upvotes: 3
Reputation: 880
You can use indexing as well. Like so:
def reorder(a, b):
tmp = [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]
tmp[0] = tmp[0][-b:] + tmp[0][:-b]
tmp[1] = tmp[1][-b:] + tmp[1][:-b]
return tmp
reorder(10, 1)
Output:
[[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]]
For the edge case where b
is greater than a/2
. Use the modulo as such:
def reorder(a, b):
sz = a//2
r = b%sz
tmp = [[i for i in range(0, sz)]] + [[f for f in range(sz, a)]]
tmp[0] = tmp[0][-r:] + tmp[0][:-r]
tmp[1] = tmp[1][-r:] + tmp[1][:-r]
return tmp
reorder(10, 7)
[[3, 4, 0, 1, 2], [8, 9, 5, 6, 7]]
This can be done for in Maurice Meyer's answer (best so far) as well.
Upvotes: 1
Reputation: 3657
You can use a double ended que which has a built in rotate()
function,
from collections import deque
def reorder(a,b):
my_arr = [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]
first_q = deque(my_arr[0])
second_q = deque(my_arr[1])
first_q.rotate(b)
second_q.rotate(b)
return [list(first_q), list(second_q)]
print(reorder(10, 1))
Upvotes: 1
Reputation: 700
If applicable I'd suggest using deque. I'd expect it to be faster that list.
import collections
def reorder(a,b):
tmp = [[i for i in range(0, a//2)]] + [[f for f in range(a//2, a)]]
for i in range(len(tmp)):
tmp[i] = collections.deque(tmp[i])
# rotates to right for positive numbers
tmp[i].rotate(b)
print d
>>> deque([3, 4, 5, 1, 2])
Upvotes: 0
Reputation: 127
You can pop the last element of each subarray b times and insert it at the beginning:
def reorder(a,b):
suba = [i for i in range(0, a//2)]
subb = [f for f in range(a//2, a)]
for i in range(b):
suba = [suba.pop(-1)]+suba
subb = [subb.pop(-1)]+subb
return [suba,subb]
In[1]: reorder(10,1)
Out[1]: [[4, 0, 1, 2, 3], [9, 5, 6, 7, 8]]
Upvotes: 1