I am writing a script where I have a list of 7 integers ranging from 66 to 95. I want this list to be pseudo-randomly different each time I call it, but I want to be sure that it never returns the same random arrangement of random numbers.
This is nestled earlier in the file:
rnd = random.Random()
If I set x to 1 in the seed and call the function like so:
rnd.seed(x)
results = [rnd.randrange(66, 96) for i in range(7)]
and then if I call the function over and over, incrementally adding 1 to x in:
rnd.seed(x)
Will I be guaranteed a different set of random arrangements of random numbers until the number of possible iterations loops? When I write this down I feel like the answer is no. And if the answer is no, is there a way to do this? The program will be opened and closed often and if this works I would start it on the seed it last closed on.
There's absolutely no way to guarantee that generating a random list of 7 integers will always be unique, short of checking the newly generated list against a database of all generated lists you've already created. Random is random, and although the chance is slim (1 in 21,870,000,000 to be precise) it will always be possible without some sort of verification of uniqueness.
Related
I got a function in another file, to recall that function i use:
app.put_number(row, column, number)
which is basically generating a matrix, but in the first column, for each row I need a random number from 1 to 20, and each number must be unique, I tried using random.randrange().
For example:
app.put_number(0, 0, random.randrange(1,21))
app.put_number(1, 0, random.randrange(1,21))
But sometimes it generates the same number and I need that each one of them to be different.
Plus I cant mess with the file with the actual function, I can only use if, else, while, for and app.put_number(row, column, number)
It would be helpful if you tagged your question with a specific language you would like to complete this task in.
Conceptually, however; you need to check the populated array every time a new number is generated to ensure that you are not inserting a number already in the array. If you want to get fancy you could even have an array of numbers and randomly choose the index of the array you are putting the numbers into, effectively "shuffling" them together.
Try using the Random.sample(). It returns unique numbers in a range
As per doc below "To choose a sample from a range of integers, use a range() object as an argument. This is especially fast and space efficient for sampling from a large population: sample(range(10000000), k=60)."
https://docs.python.org/3/library/random.html
One solution is to keep the generated numbers in a list and then calling the random number generator until it gives a number that is not present in your list of already generated numbers.
I have written a script where I need a unique random number every time I run that script. Just for explaination: suppose that I want my script 5 times. Now I want number generated in all times should be unique?
I have found a lot of infomation about random number uniqueness but those are for one time only.
If you think it is not possible then is there any alternative way etc.?
You could use uuid to generate RFC 4122 UUIDs (Universally Unique IDentifiers). For example uuid4 generates a random UUID:
In [1]: import uuid
In [2]: u = uuid.uuid4()
In [3]: u
Out[3]: UUID('deb1064a-e885-4ebc-9afc-f5291120edf8')
To get the number, access the int attribute of uuid.UUID objects:
In [4]: u.int
Out[4]: 242844464987419882393579831900689854160
Unique and random are contradictory. For anything that's genuinely random there is a (small, maybe infinitessimal) chance of repetition.
If you want something less unwieldy (but less universally unique) than UUIDs you can roll your own combination of a random number (with a small chance of repetition) and a number derived from the time (for example the Unix epoch, which won't ever repeat for a single instance if the script is run less often than once per second).
If the random number is used as part of (say) a filename you can generate a name and then check whether the file already exists. If it does, then reject the random number as already used, and generate another one. Or if you really need to, you could store all random numbers already used somewhere. Load them before each run, add the new number and save after each run.
Finally there are pseudo-"random" generators of the form X(n+1) = (X(n)*a + b) mod M. These are hopeless for security / cryptography because given a few members of the sequence, you can discover the algorithm and predict all future numbers. However, if that predictability is unimportant, then with appropriate constants you can guarantee no repeats until all M members of the sequence have been generated. The numbers are not at all random, but they may appear random to a casual observer.
I am relatively new to programming, so be easy on me.
I have made a program (much like a magic 8 ball) that the user asks a question, and then I have created a list with all my answers inside of it (14 answers). My program shuffles all the answers, but then I now need to assign every piece of data (using a random number generator from 1-14 (which I've completed), and then have it match the shuffled data with a random number and print that.
I have created the random number generator, and the answer list shuffles. I just need to know how to assign the number to the strings in my list, and then print that one string.
Lists have indices; if your number is between 0 and 13 (inclusive), then you can just use that directly on your list:
print(answers[random_number])
However, the random module has a dedicated function for just this use case; random.choice() picks one value from a sequence at random:
print(random.choice(answers))
No need to shuffle anything that way..
Demo:
>>> import random
>>> answers = ['Without a doubt!', 'Hmmm, not so sure', 'By the winds, set sail now!', 'Oh no, no NO NO!!']
>>> print(random.choice(answers))
Hmmm, not so sure
>>> print(random.choice(answers))
Oh no, no NO NO!!
I have a list which I shuffle with the Python built in shuffle function (random.shuffle)
However, the Python reference states:
Note that for even rather small len(x), the total number of permutations of x is larger than the period of most random number generators; this implies that most permutations of a long sequence can never be generated.
Now, I wonder what this "rather small len(x)" means. 100, 1000, 10000,...
TL;DR: It "breaks" on lists with over 2080 elements, but don't worry too much :)
Complete answer:
First of all, notice that "shuffling" a list can be understood (conceptually) as generating all possible permutations of the elements of the lists, and picking one of these permutations at random.
Then, you must remember that all self-contained computerised random number generators are actually "pseudo" random. That is, they are not actually random, but rely on a series of factors to try and generate a number that is hard to be guessed in advanced, or purposefully reproduced. Among these factors is usually the previous generated number. So, in practice, if you use a random generator continuously a certain number of times, you'll eventually start getting the same sequence all over again (this is the "period" that the documentation refers to).
Finally, the docstring on Lib/random.py (the random module) says that "The period [of the random number generator] is 2**19937-1."
So, given all that, if your list is such that there are 2**19937 or more permutations, some of these will never be obtained by shuffling the list. You'd (again, conceptually) generate all permutations of the list, then generate a random number x, and pick the xth permutation. Next time, you generate another random number y, and pick the yth permutation. And so on. But, since there are more permutations than you'll get random numbers (because, at most after 2**19937-1 generated numbers, you'll start getting the same ones again), you'll start picking the same permutations again.
So, you see, it's not exactly a matter of how long your list is (though that does enter into the equation). Also, 2**19937-1 is quite a long number. But, still, depending on your shuffling needs, you should bear all that in mind. On a simplistic case (and with a quick calculation), for a list without repeated elements, 2081 elements would yield 2081! permutations, which is more than 2**19937.
I wrote that comment in the Python source originally, so maybe I can clarify ;-)
When the comment was introduced, Python's Wichmann-Hill generator had a much shorter period, and we couldn't even generate all the permutations of a deck of cards.
The period is astronomically larger now, and 2080 is correct for the current upper bound. The docs could be beefed up to say more about that - but they'd get awfully tedious.
There's a very simple explanation: A PRNG of period P has P possible starting states. The starting state wholly determines the permutation produced. Therefore a PRNG of period P cannot generate more than P distinct permutations (and that's an absolute upper bound - it may not be achieved). That's why comparing N! to P is the correct computation here. And, indeed:
>>> math.factorial(2080) > 2**19937 - 1
False
>>> math.factorial(2081) > 2**19937 - 1
True
What they mean is that permutations on n objects (noted n!) grows absurdly high very fast.
Basically n! = n x n-1 x ... x 1; for example, 5! = 5 x 4 x 3 x 2 x 1 = 120 which means there are 120 possible ways of shuffling a 5-items list.
On the same Python page documentation they give 2^19937-1 as the period, which is 4.something × 10^6001 or something. Based on the Wikipedia page on factorials, I guess 2000! should be around that. (Sorry, I didn't find the exact figure.)
So basically there are so many possible permutations the shuffle will take from that there's probably no real reason to worry about those it won't.
But if it really is an issue (pesky customer asking for a guarantee of randomness perhaps?), you could also offload the task to some third-party; see http://www.random.org/ for example.
Let's say I have a list in python with several strings in it. I do not know the size. How can I run a loop to do an operation on 2 random elements of this string?
What if I wanted to favour a certain subset of the strings in this randomization, to be selected more often, but still make it possible for them to not be chosen?
you need to look into random module. It has for example a random.choice function that lets you select a random element from a sequence or a random.sample that selects given number of samples, it's easy to account for different weights too.
explain better your problem, what operations and what elements you're focusing?
regarding the problem with the elements beeing chosen more often, give each string an "chance multiplier", each comparison you multiply a number between 1 and 10 and the chance multiplyer of the string, if the result is higher than X (say... 5), so it select the string, if not, it searches for another string. this way, strings with higher multipliers will have more chance to be selected