0

Suppose I am given an input integer in the range 0 to 10000. I would like a one to one function that maps this integer to another seemingly random integer in the same range. Essentially, I want something like this:

import random
random.seed(0)
out = list(range(10001))
random.shuffle(out)
mapper = {ii:oo for ii, oo in enumerate(out)}

>>> mapper[0]
6853
>>> mapper[1]
3631
>>> mapper[3]
421

The only problem is that this Python code gets executed thousands of times per frame, so I don't want to shuffle the list each time because that slows it down too much. But I don't have any global storage where the list can be computed once and accessed each frame (I'm using a Python effector in Cinema 4D, so the whole python script gets executed for every single clone). So I need another faster solution that can get what I'm looking for.

I assume there is some much more efficient mathematical function I could use instead that would get me a very similar result, essentially just taking an integer and mapping it to another pseudo random integer in a given range, while producing the same result each time the script is run. Any ideas?

joejoejoejoe4
  • 1,206
  • 1
  • 18
  • 38
  • Does this answer your question? [Algorithm or formula that can take an incrementing counter and make it appear uniquely random](https://stackoverflow.com/questions/65661013/algorithm-or-formula-that-can-take-an-incrementing-counter-and-make-it-appear-un) – Peter O. Feb 05 '21 at 03:15

2 Answers2

-1

random.randint is what is right for you, you can create a generator from it if you need:

import random
def random_integer(lower_bound, higher_bound):
  while True:
    yield random.randint(lower_bound, higher_bound)

int_gen = iter(random_integer(0, 10001))

# And then use it:

>>> next(int_gen)
6853
>>> next(int_gen)
9883
>>> next(int_gen)
7782
...
DDomen
  • 1,808
  • 1
  • 7
  • 17
-1

What you're looking for is a hash function, modulo the range you're interested in. The default hash function in python works trivially on integers however, so it won't have the 'random' effect that you are looking for. CRC32 is probably a good choice and very fast.

A full example with output over a smaller input range is

import zlib

max_value = 10

for x in range(max_value):
    print(x, zlib.crc32(bytes(x)) % max_value)

What you can do is then save this as a dictionary and just look up the value when you need it

cached_hash = {x: zlib.crc32(bytes(x)) % max_value for x in range(max_value)}

Which will be faster depending on how many times you need to find the random int for an int compared to the size of max_value

ScienceSnake
  • 608
  • 4
  • 15