Random int without importing 'random'
Asked Answered
P

5

13

is there a way to let the program select a random number between say 1 and 1,000 without importing random?

Polk answered 9/4, 2014 at 0:36 Comment(3)
Why can't you just import random? You could start writing your own random number generation code, but why would you?Minatory
Sure, just write your own PRNG, or perhaps read from the system's (e.g. /dev/random).Athey
Of course there is: xkcd.com/221 (trivially translated into Python). Put another way, you'd be more likely to get useful answers if you told us where you were going with this.Triplet
F
12

Based on random source code:

def randint(a, b):
    "Return random integer in range [a, b], including both end points."
    return a + randbelow(b - a + 1)

def randbelow(n):
    "Return a random int in the range [0,n).  Raises ValueError if n<=0."
    if n <= 0:
       raise ValueError
    k = n.bit_length()
    numbytes = (k + 7) // 8
    while True:
        r = int.from_bytes(random_bytes(numbytes), 'big')
        r >>= numbytes * 8 - k
        if r < n:
            return r

def random_bytes(n):
    "Return n random bytes"
    with open('/dev/urandom', 'rb') as file:
        return file.read(n)

Example:

print(randint(1, 1000))

You could also implement random_bytes() using PRNG.

Frowsty answered 9/4, 2014 at 5:8 Comment(0)
P
4

There are many interesting ways to generate randomness without resorting to random (or numpy). For instance, you can use the built in hash function:

def rand_generator(seed, N=10**6, a=0, b=10, integer = True):
    '''For a given seed, this function returns N pseudo-random between a and b'''
    rands =[]
    if integer:
        for i in range(N):
            num = int(a+(b-a)*(abs(hash(str(hash(str(seed)+str(i+1)))))%10**13)/10**13)
            rands.append(num)
        return rands
    else:
        for i in range(N):
            num = a+(b-a)*(abs(hash(str(hash(str(seed)+str(i+1)))))%10**13)/10**13
            rands.append(num)
        return rands

This will generate a list of uniformly distributed pseudo-random numbers between 0 and 1. Like the random number generators in random and numpy the sequence is fully deterministic for a given seed.

Histogram of the function's output.

This algorithm is in no way cryptographically safe but it should be sufficient to answer your question.

If storing the entire list undesirable then the same idea can take the form of a generator expression. After setting the values for a, b, N, and seed as above:

randnum = (int(a+(b-a)*(abs(hash(str(hash(str(seed)+str(j+1))))) % 10**13)/ 10**13) for i in range(N))

is an iterator which generates the next number in the sequence via

>>> next(randnum)
    5

This can be made even neater as follows:

def random(seed = None, a=0, b=10,  N=10**12, integer=True):
    '''Pass a seed to generate new sequence, otherwise next value is returned.'''
    if seed:
        print("Starting new sequence.")
        global _rand_generator 
        if integer: 
            hash_plus = lambda j: int(a + (b-a)*(abs(hash(str(hash(str(seed) + str(j+1))))) % 10**13)/ 10**13)
        else:
            hash_plus = lambda j: a + (b-a)*(abs(hash(str(hash(str(seed) + str(j+1))))) % 10**13)/ 10**13
        _rand_generator =  (hash_plus(j) for j in range(N))
    try:
        return next(_rand_generator)
    except:
        print("Random seed required.")
            

To generate a random sequence pass a seed to the function.

>>> random(42)
Starting new sequence.
    8 

Call the function again without a seed to yield the next random number/integer in the sequence.

>>> for i in range(10): 
...     print(random())
    3
    4
    6
    5
    5
    9
    2
    2
    4
    0

To start a new sequence, simply call the function again with a new seed.

>>> random(666)
Starting new sequence.
    5
Passion answered 20/3, 2021 at 20:48 Comment(3)
Welcome to SO, and kudos for your thorough 1st answer; but please do not include meta-commentary in answers (edited out).Dimitri
Notice only that (hidden in the title) is the requirement for int(egers).Dimitri
Good point, I'll add the transformation to int as an edit.Passion
G
1

assuming you want integers.

import numpy as np
np.random.randint(1,1000)
Grocery answered 9/4, 2014 at 0:44 Comment(3)
Hey, I forgot to mention I cannot import anything. This is one of the rules for this homework. BTW, this is a small part of the homework, it's not like i'm asking you guys to write the program for me. SO please don't get mad at me :)Polk
You could make a roulette wheel type setup where you have them hit the space bar and read the milliseconds from the computer clock.Grocery
I'd let you pay me for the answer but then you would be doing it for the rest of your life. Too bad. Enjoy your homework. Hint read this docs.python.org/2/library/datetime.htmlGrocery
M
0
#method one, set new seed every time random is needed


seed = "seed" #can be int or string, varies between compilings of the game
possibilities = 3 #0,1,2

hash(str(seed))%possibilities

hash(str(0))%3 #single random number between 0,1,2 (inc) seed is 0


#method two, generate a random list of numbers


size = 100 #length of list
possibilities = 2 #0,1

[hash(str(seed))%possibilities for seed in range(size)]

[hash(str(seed))%5 for seed in range(100)] #generates a list of numbers between 0,1,2,3,4 (inc) with the size of 100
hash(" ")%6


[hash(str(seed))%2 for seed in range(100)].count(1) #validity check. output is ~50

i wrote this program to help with this problem

Muscid answered 4/8, 2022 at 6:49 Comment(0)
S
0

Lucky me, the environment I'm in happens to have datetime available already. Datetime would normally require an import so this doesn't solve the problem w/o any imports (which is what I think the OP was getting at)

And, let's be clear, this is not a truly random number but it's close enough for many practical applications.

int( str( datetime.now().microsecond )[-1] ) 
# yields a number from 0 through 9

int( str( datetime.now().microsecond )[-2:] ) 
# yields a number from 0 through 99
Supererogate answered 2/5 at 23:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.