Pradeep Shanbhag
Pradeep Shanbhag

Reputation: 477

Shifting String characters

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

Answers (3)

Emil M George
Emil M George

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

lenik
lenik

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

Zain Arshad
Zain Arshad

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

Related Questions