I have a similar implementation - except using generators and itertools
.
What @wrkyle is doing is that he is replacing the values by constructing new lists. Imagine if you would like to rotate 1000000000 times. You'd have to construct a new list 1000000000 times. It's not very memory efficient.
For scalability, I propose that we generate an infinite sequence and just call the values as needed. I designed the rotate
method so that it takes in an argument for the number of turns; this way the user does not have use any loops to cycle through the pieces - just calculate how many positions are to be shifted, and update the values once.
from itertools import cycle, islice
from random import randint
class Piece:
def __init__(self):
self._values = cycle([randint(10, 99) for _ in range(4)])
self._turns = 0
def __str__(self):
positions = list(islice(self._values, 0, 4))
disp = (
"piece after %s turns:" % (self._turns) + "\n\n" +
" %s \n" % (positions[0]) +
"%s 00 %s\n" % (positions[3], positions[1]) +
" %s \n" % (positions[2])
)
return disp
def rotate(self, num_turns, direction="right"):
self._turns += num_turns
if direction == "right":
self._values = cycle(islice(self._values,
2 + num_turns % 4,
6 + num_turns % 4)
)
else:
self._values = cycle(islice(self._values,
0 + num_turns % 4,
4 + num_turns % 4)
)
Now if you run the following code, by rotating right -
p = Piece()
# rotate 4 times
for _ in range(4 + 1):
print(p)
p.rotate(1, direction="right")
You get:
piece after 0 turns:
57
86 00 89
14
piece after 1 turns:
86
14 00 57
89
piece after 2 turns:
14
89 00 86
57
piece after 3 turns:
89
57 00 14
86
piece after 4 turns: # confirm it returns to original position
57
86 00 89
14
Of course, you can change the default argument of the rotate
method to "left" so that it rotates left.