views:

89

answers:

5

My Python code generates a random number between 0 and 35 and stores that number as 'random'. I am looking to compare 'random' against several ranges of numbers to determine which of three groups it falls into and assign another value to 'winning' based on which group 'random' is in. The groups are: 0-16, 16-34, and 34-36. 'winning' always returns 2 though. Here's what I've tried so far.

import random #start python random number generator
random = random.randrange(36) #calls a random number between 0-35 and stores value
print random #test

for random in range(0, 16):
   winning = 0
for random in range(16, 34):
   winning = 1
for random in range(34, 36):
   winning = 45
print winning #test

Thank you in advance for any help that you can give! This is my first time programming with Python.

+4  A: 

First of all, please don't name your variable random. It shadows the random module name and you won't be able to use the random module in the rest of scope because of this.

So let's call the result rnd.


You should use if rnd in range(0, 16): ... instead of for. The syntax

for a in list_:
  foo(a)

will extract every element in the list_ one by one, assign it to a each time, then call the body. As seen from the for it is a loop. Therefore, you are actually setting winning = 0 17 times, etc.

On the other hand, the syntax

if b in list_:
  foo(b)

which can be seen as

if (b in list_):
  foo(b)

will check if b is an element of list_, and execute the body if the condition is true (the in is also an operator.)


You shouldn't use in range(...) to check if a number is in a numeric range because searching in a list takes linear time. The Pythonic way is to use the a <= b < c notation:

if 0 <= rnd < 16:
  winning = 0

But actually it can be written more simply (no matter which language you use) as

if rnd < 16:
  winning = 0
elif rnd < 34:
  winning = 1
else:
  winning = 45
KennyTM
+3  A: 

You should use if instead of for. for is a loop keyword.

if random in range(0, 16):
    winning = 0

Actually this is not a great use of range since it will generate a full list of all numbers and then check each number to see if it equals random. It would be more efficient to do some simple comparisons:

if 0 <= random < 16:
    winning = 0

# The above is a shorthand syntax for this:
# if 0 <= random and random < 16
John Kugelman
Yes! Thank you! That worked wonderfully, and confirmed my initial guess that if would have worked.
Kevin
+0.1 for answering the OPs question, +0.9 for giving a more pythonic (and better in general) solution
Wayne Werner
@Kevin: To confirm such a guess, try running the guessed solution.
John Machin
+1  A: 

One implementation of what I think you want:

def getWinning(number):
    ranges = {
        0: (0, 16),
        1: (16, 34),
        45: (34, 36)
    }

    for key in ranges :
        low, high = ranges[key]
        if low <= number < high:
            return key
psicopoo
+2  A: 

Using bisect.bisect is a nice way to replace the if statements:

import random 
import bisect

num = random.randrange(36) 
print num 

grid=(0,16,34,36)
winning=bisect.bisect(grid,num)
winning=45 if winning==2 else winning
print(winning)

PS. Do not call your random number random. Doing so clobbers the module of the same name (making it impossible to call random.randrange, say, a second time). This leads to a potentially hard-to-find bug since the exception (AttributeError) can occur miles away from the true cause of the error.

unutbu
`winning` should be 45, not 2, when the random number is ≥34.
KennyTM
Ahh...that's why the generator was giving me problems. Thanks!
Kevin
Thanks, @KennyTM.
unutbu
+2  A: 

This is bit advanced code structure, but really not so much complicated.

from random import choice

# Do list weighted by the winning chances
winning=[0]*16+[1]*18+[45]*2

for lottery in range(10):
    win =  choice(winning)
    print("Round %i:\t" % (lottery+1) +
          ("You won $%i" % win if win
           else "No win this time")
          )
Tony Veijalainen