'Need random value from last x elements in a list

I'm trying to get a random number from a list within a specific range, without using any module.

Input list looks like li = [12,44,55,64,34,54,56,43,56,9,87,89]

I need a function where I should pass this list and x as inputs and get a random element from last x elements in the given list.

For example: val = getRandom(li, 4), the result val should be any one these values: 56,9,87,89

I tried with random module, it is working fine.

def getRandomNumber(li, x):
    return random.choice(li[-x:])

Can anyone please help me to do achieve the same without the random module?



Solution 1:[1]

Since there's no answer yet that doesn't use random module... (Tested on CPython 3.6, 3.7, 3.8)

This program uses no imports, gives a (potentially) satisfactory "random" result. Remember that no random number generator is perfect, and this one certainly isn't the pick of the litter, but again, no imports

s = 0
def randn(n):
    global s
    s += 1
    return hash(str(s)) % n

def get_random(sequence, n):
    i = randn(n) - n + len(sequence)
    return sequence[i]

li = [12,44,55,64,34,54,56,43,56,9,87,89]

print(get_random(li, 4))

Explanation:

s = 0 this is the inital state (seed) of the random algorithm

global s; s += 1 this increments the state every time randn is called so we don't get the same value every time

hash(str(s)) the builtin hash creates an int hash of the given object. The reason why we convert to string first, is because the hash of an int directly is (usually) itself. The hashes of strings are consistent over the runtime of the program, but not over restarting the program (Tested in CPython), so even starting with s = 0 always, we will get a different series of numbers upon restarting the program.

% n we are considering the hash result to be 1. pseudo-random, and 2. large. Therefore if we take the modulus on n, and n is much smaller than the (large) value of the hash, the result should be a pseudo-random value from 0 to n-1.

i = randn(n) - n + len(sequence) get a random index of the last n indices of the sequence

Solution 2:[2]

Use random module

import random

li = [12,44,55,64,34,54,56,43,56,9,87,89]

def getRandom(ls, x):
    return random.choice(ls[-x:])

print(getRandom(li, 4))

Solution 3:[3]

To do this without copying a slice of the list, you can use random.randint(-x, -1) to generate an index in the range from -x to -1 inclusive (see the docs). When you use a negative number as an index, it's calculated as an offset from the end of the list.

Solution 4:[4]

Maybe you could try in this approach:

     import random

     li = [12,44,55,64,34,54,56,43,56,9,87,89]

     val = random.choice(li[-4:])

if you print your val, the answer should be one of last four number, for example:

     89

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 kaya3
Solution 4 wz 98