Reputation: 477
Recently I got a task to shift characters of a string as shown below sample
s = 'abcd'
right shift by 2
output: 'cdab'
I used below code and it works fine.
l1=[]
l2=[]
s='abcs'
l1=list(s)
loop = 0
rightshift = 2
while loop < rightshift:
l2=[]
l2=l1[1:]
l2.append(l1[0])
l1=[]
l1=l2
loop += 1
print('After shift ' , l1)
However, if we have a large number like 544645655, it takes a lot of time. Do we have any other alternative method?
Some more examples(where s='abcd')
bcda 1st shift
cdab 2nd shift
dabc 3rd shift
abcd 4th shift
bcda 5th shift
Upvotes: 1
Views: 1896
Reputation: 371
You can use modular arithmetic for reducing number of shifts for large numbers:
s = "abcd"
leftshift = 544645655 # using left shift as per sample output in question
# for rightshift, use negative number
N = leftshift % len(s) # reduce shifts using modulo, explained below
print((s+s)[N:N+len(s)])
You can also use: print(s[N:] + s[:N])
for the print, as other answers show.
Output:
dabc
Explanation:
For numbers greater than 4 (string length), the pattern just repeats. You can use modular arithmetic to convert it to a number within [0,3].
a % b
below denotes the modulus operation (It is equivalent to remainder
of division a / b
for positive numbers)
abcd # leftshift = 0 (0 % 4 = 0) [leftshift % len(s) = N]
bcda # leftshift = 1 (1 % 4 = 1)
cdab # leftshift = 2 (2 % 4 = 2)
dabc # leftshift = 3 (3 % 4 = 3)
abcd # leftshift = 4 (4 % 4 = 0)
bcda # leftshift = 5 (5 % 4 = 1)
cdab # leftshift = 6 (6 % 4 = 2)
dabc # leftshift = 7 (7 % 4 = 3)
abcd # leftshift = 8 (8 % 4 = 0)
^ repeating pattern ^ you only have to shift by this number
So to shift by 544645655
, we only have to shift by 544645655 % len(s) = 3
>>> s = "abcd"
>>> (s+s)
'abcdabcd'
We take the slice of length len(s) at position 0 like this:
'abcdabcd'
^^^^
>>> (s+s)[:len(s)]
'abcd'
Now all we need is move this slice like this:
abcdabcd
^^^^
>>> (s+s)[3:3+len(s)] # 3 is the leftshift count
'dabc'
Put in the modular expression N = leftshift % len(s)
instead of 3:
>>> leftshift = 5
>>> N = leftshift % len(s) # N = 1
>>> (s+s)[N:N+len(s)]
'bcda'
Upvotes: 2
Reputation: 23528
The easiest way to move characters is:
N = 3
s = s[N:] + s[:N]
or if you prefer to drive on the opposite side if the road:
s = s[-N:] + s[:-N]
Play with those and use the one that makes you happy.
Upvotes: 2
Reputation: 1907
If your string is abcd
, then performing a right shift of 3 would convert the string into bcda
not cdab
(It is right shift of 2 not 3).
As stated in @lenik's answer, you can use string splicing to get this done, use this simple method that will do right shift as well as left shift:
def shift(s, op, n):
if op == 'left':
return s[n:] + s[:n]
elif op == 'right':
return s[-n:] + s[:-n]
else:
print('Invalid operation')
print(shift('abcd', 'right', 3))
Output: bcda
Upvotes: -1