Wong Li Zong
Wong Li Zong

Reputation: 1

Generate 4 digits number but excluding all the numbers with any 0

I would like to generate 4 digits random number in Python but exclude all the numbers that have a "0" inside. For example, 9230, 2012 will not be accepted since there is a 0.

My code is:

def my_custom_random():
    exclude=[0]
    randInt = randint(1000, 9999)
    return my_custom_random() if randInt in exclude else randInt 

def Q3a():        
      RandomNumber = my_custom_random())  
      print(RandomNumber)

Q3a()

But this code is not working. Anyone can help me ? Thanks.

Upvotes: 0

Views: 641

Answers (3)

bardsss
bardsss

Reputation: 1

I hope it will help you

    import random
    
    def my_custom_random():
        exclude = 0
        digits = [0,1,2,3,4,5,6,7,8,9]
        randNumber = random.sample(digits,4) #List of integers Ex. [2,9,1,6]
        while exclude in randNumber:
            randNumber = random.sample(digits,4)
        return map(str,randNumber) #map(str, x) -> transform [2,9,1,6] to ['2','9','1','6']

    def Q3a():        
        randNumber = my_custom_random()  
        randNumber = "".join(randNumber) # ['2','9','1','6'] to '2916'
        print(int(randNumber))

    Q3a()

In digits you can omit the 0, so you can write less code. This way you will never have numbers with zero.

    def my_custom_random():
        digits = [1,2,3,4,5,6,7,8,9]
        randNumber = random.sample(digits,4)
        return map(str,randNumber)

Upvotes: 0

jpmarinier
jpmarinier

Reputation: 4733

Congratulations for not picking the easy but expensive solution, consisting in calling 4 times the random number generator for a number between 1 and 9 inclusive.

we can basically keep your recursive scheme, but delegate the hard work to another function, isBadNumber(). Like this:

def my_custom_random():
    randInt = random.randint(1111, 9999)
    return  my_custom_random() if isBadNumber(randInt) else randInt 

To decide whether some number is acceptable or not, we need some auxiliary function that returns the list of digits:

# get at least k digits for a number in some arbitrary base:
def xdigits(k, base, n):
    if (n < base):
        res = (k-1)*[0] + [n]
    else:
        res = xdigits(k-1, base, n // base) + [n % base]
    return res

Trying:

>>> 
>>> q.xdigits(4,10,56)
[0, 0, 5, 6]
>>> 
>>> q.xdigits(4,10,123456)
[1, 2, 3, 4, 5, 6]
>>> 
>>> q.xdigits(4,10,7702)
[7, 7, 0, 2]
>>> 

Thus we can write our isBadNumber() function like this:

def isBadNumber(n):
    if ((n < 1111) or (n > 9999)):
        return True

    ds = xdigits(4, 10, n)
    if (min(ds) < 1):
        return True   # having a zero

    return False      # passed all tests OK.

Addendum: a method without rejection:

Rejection costs CPU time, so it is always nice if we can do without it. For each of the 4 digits, there are 9 possibilities, 1 to 9 inclusive. Hence the overall number of solutions is 94, hence 6561. As programmers use to do, we can decide to number them from 0 to 6560 inclusive.

So we can pick one of them like this:

>>> 
>>> import random
>>> import functools as fn
>>> 
>>> random.randint(0,6560)
3952
>>> 

If we express this number in base 9 (not 10), we get 4 digits between 0 and 8 inclusive. This is exactly what we need, provided we add 1 to every digit.

>>> 
>>> q.xdigits(4,9,3952)
[5, 3, 7, 1]
>>> 

We add 1 to every digit, giving [6, 4, 8, 2]. Hence, the 3952-th solution is number 6482.

Going from 3952 thru [5,3,7,1] to 6482 can be done using some simple Python data massaging:

>>> 
>>> ds1 = list(map(lambda n: n+1, [5, 3, 7, 1]))
>>> ds1
[6, 4, 8, 2]
>>> 
>>> fn.reduce(lambda acc, d: acc*10 + d, ds1)
6482
>>> 

So overall the rejection-free code would be like this:

def my_custom_random():
    randomRank = random.randint(0, 9**4 - 1)
    ds0 = xdigits(4, 9, randomRank)
    ds1 = list(map(lambda n: n+1, ds0))
    num = functools.reduce(lambda acc, d: acc*10 + d, ds1)
    return num

Upvotes: 1

rossum
rossum

Reputation: 15693

Basically, if you don't want zeros then don't pick zeros. Pick from [1..9] only, so you never pick a zero.

Here is some pseudocode; my Python is not good.

function noZeros()
  digits <- [1,2,3,4,5,6,7,8,9] // Zero omitted.
  result <- 0
  repeat 4 times
    result <- 10 * result;
    thisDigit <- pick a random entry from digits array
    result <- result + thisDigit
  end repeat
  return result
end function noZeros

I am sure you can write a better version in Python.

Upvotes: 0

Related Questions