Rotate sequences left or right

Updated TrustyTony 1 Tallied Votes 660 Views Share

Another quick code over breakfast inspired by 'spying' the other forums.

Gribouillis commented: nice +13
""" Rotate sequences right or left
    >>> rot_right(arr)
    [(7, 4, 1), (8, 5, 2), (9, 6, 3)]
    >>> p(rot_right(arr))
    (7, 4, 1)
    (8, 5, 2)
    (9, 6, 3)
    ----------------------------------------
    >>> p(rot_right(rot_right(arr))
      )
    (9, 8, 7)
    (6, 5, 4)
    (3, 2, 1)
    ----------------------------------------
    >>> p(rot_right(rot_right(rot_right(arr))))
    (3, 6, 9)
    (2, 5, 8)
    (1, 4, 7)
    ----------------------------------------
    >>> p(rot_right(rot_right(rot_right(rot_right(arr)))))
    (1, 2, 3)
    (4, 5, 6)
    (7, 8, 9)
    ----------------------------------------
    >>> p(rot_right(rot_left(arr)))
    (1, 2, 3)
    (4, 5, 6)
    (7, 8, 9)
    ----------------------------------------
    >>> a =['***',
            ' * ',
            '   ']
    >>> p(a)
    ***
     * 
    ----------------------------------------
    >> p(map(''.join, rot_right(a)))
      *
     **
      *
    >>> p(map(''.join, rot_left(a)))
    *  
    ** 
    *  
    ----------------------------------------
    >>> p(map(''.join, rot_left(rot_left(a))))
       
     * 
    ***
    ----------------------------------------
"""

def p(a, sep=40*'-'):
    """ print sequences in separate lines and line separation sep """
    for line in a: print(line)
    print(sep)

def rot_left(a):
    return list(zip(*a)[::-1])

def rot_right(a):
    return list(zip(*a[::-1]))

if __name__ ==  '__main__':
    arr = [[1,2,3],[4, 5, 6], [7, 8, 9]]
    p(arr)
    p(rot_right(rot_right(rot_right(arr))))   
    p(rot_right(rot_right(rot_right(arr))))
TrustyTony 888 pyMod Team Colleague Featured Poster

The sequences does not need to be of square arity for functions to work, here another helper for the 'tetris' case:

>>> a = ['***', ' * ']
>>> def strrot(string_seq, rotation=rot_left, fun=''.join, times=1):
	for count in range(times):
		string_seq = map(fun, rotation(string_seq))
	return '\n'.join(string_seq)

>>> strrot(a)
'* \n**\n* '
>>> print strrot(a)
* 
**
* 
>>> print strrot(a, times=2)
 * 
***
>>> print strrot(a, times=3)
 *
**
 *
>>> print strrot(a, rotation=rot_right)
 *
**
 *
>>> print strrot(a, rotation=rot_right, times=2)
 * 
***
TrustyTony 888 pyMod Team Colleague Featured Poster

Another interesting aplication for the generalized principle:

""" rotating histogram by functions rot_left, rot_left and strrot """

def p(a, sep='', groupsep=40*'-'):
    """ print sequences in separate lines and line separation sep """
    for line in a: print(sep.join(line))
    print(groupsep)

def rot_left(a):
    return list(zip(*a)[::-1])

def rot_right(a):
    return list(zip(*a[::-1]))

def strrot(string_seq, rotation=rot_left, fun=''.join, times=1):
	for count in range(times):
		string_seq = map(fun, rotation(string_seq))
	return string_seq

if __name__ == '__main__':
    histo = """
red    ***********
yellow *************
brown  ****
"""
    histo = histo.split('\n')
    histo = [' '.join(''.join(word[::-1]) for word in line.split(' '))  for line in histo]
    linemax = len(max(histo, key=len))
    histo = [line.ljust(linemax) for line in histo if line]
    p(strrot(histo), sep =' ')
""" Output:
  *  
  *  
* *  
* *  
* *  
* *  
* *  
* *  
* *  
* * *
* * *
* * *
* * *
     
  y  
  e b
  l r
r l o
e o w
d w n
----------------------------------------
"""
Gribouillis 1,391 Programming Explorer Team Colleague

Here is how I would code it to get rid of the 'rotation' argument and make it a little faster

def strrot(string_seq, times = 1):
    times %= 4
    if times % 2:
        string_seq = reversed(zip(*string_seq)) if times == 1 else zip(*reversed(string_seq))
        return [''.join(t) for t in string_seq]
    else:
	    return reversed([s[::-1] for s in string_seq]) if times else string_seq

To rotate right, pass times = -1, or -44445 :)

TrustyTony 888 pyMod Team Colleague Featured Poster

Thanks fro your analysis Gribouillis, interesting rotation of reversed, zip and * for odd cases. I did little different single if case-like statement vesion of it, so:

""" rotating histogram by functions rot_left, rot_left and strrot """

def p(a, sep='', groupsep=40*'-'):
    """ print sequences in separate lines and line separation sep """
    for line in a: print(sep.join(line))
    print(groupsep)

def rot_left(a):
    return list(zip(*a)[::-1])

def rot_right(a):
    return list(zip(*a[::-1]))

def strrot(string_seq, times = 1):
    times &= 0b11
    if not times:
        return string_seq
    elif times == 2:
        return list(reversed([s[::-1] for s in string_seq]))
    elif times == 3 :
       string_seq = zip(*reversed(string_seq))
    else:
        string_seq = list(reversed(zip(*string_seq)))
        
    return [''.join(t) for t in string_seq]
    

if __name__ == '__main__':
    t = ['***', '*  ']
    for count in range(1,5):
        print('Left rotate %i:\n' % count)
        p(strrot(t, times=count))
    print(60*'=')
    print('Right rotate variations')
    p(strrot(t, -44445))
    p(strrot(t, -1))
    p(strrot(t, 3))
Archenemie 2 Junior Poster

The python deque (double ended que) is good for left/right rotation

from collections import deque # Double-ended Que

stringToRotate = "hello"

alpha = 'hello' # This is your reference

dq = deque(alpha) # make double ended

amount = 2

dq.rotate(amount)# positive values drags to the right - negative to the left

rotatedString = "" # define for later

for letter in stringToRotate:

    if letter in alpha:

        index_alpha = alpha.index(letter) # Get original position of letter
        rotatedString += dq[index_alpha] # add the rotated letter to string
        
print rotatedString
TrustyTony commented: Inappropriate for 2-d case -3
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.