iterate over all values of a range in random order.
related to http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/466177
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | import array, random
TEADELTA = 0x9e3779b9L
TEAROUNDS = 32
TEASBOXSIZE = 128
TEASBOXSHIFT = 7
class randrange(object):
def __init__(self, start, stop):
self.start = start
self.max = stop - start
self.sbox = array.array('I', [ random.randint(0, 0xffffffffL)
for i in range(TEASBOXSIZE) ])
bits = 0
while (1 << bits) < self.max:
bits += 1
self.left = bits / 2
self.right = bits - self.left
self.mask = (1 << bits) - 1
if TEASBOXSIZE < (1 << self.left):
self.sboxmask = TEASBOXSIZE - 1
self.kshift = TEASBOXSHIFT
else:
self.sboxmask = (1 << self.left) - 1
self.kshift = self.left
def __iter__(self):
enc = 0
for i in range(self.max):
c = self.max
while c >= self.max:
c = enc
enc += 1
s = 0
for j in range(TEAROUNDS):
s += TEADELTA
c ^= (self.sbox[(c ^ s) & self.sboxmask] << self.kshift)
c = (c + s) & self.mask
c = ((c << self.left) | (c >> self.right)) & self.mask
yield self.start + c
def __len__(self):
return self.max
|
this implements a modified (variable block size) TEA cipher by Niels Provos . a similar version in C is available in the libdnet Python extension module (http://libdnet.sf.net/) - see dnet.rand.xrange()
Tags: algorithms
it is quicker to use random.shuffle()
hrr, i should have given an example... this is meant to handle cases where the results of range() will not fit in memory - e.g. a randomized walk over all values of the IP address space, or even sys.maxint, etc.