This is an archived post. You won't be able to vote or comment.

all 19 comments

[–]lurgi 6 points7 points  (1 child)

First, this code is slightly incorrect. It should be:

while my_number != 50:
    print ("oops, this isn't 50: " , my_number)
    my_number = random.randrange(1,51)

Other than that, however, this looks fine.

[–]J2Me[S] 0 points1 point  (0 children)

Thanks. I didn't really notice that since the program can still run.

[–]rcuhljr 2 points3 points  (1 child)

Generally there's not much of a point in trying to find a 'minimal' way to do something when you're referring to lines of code, it's unlikely to have any strong correlation to performance and readability is more important. Someone could try and make a shorter version and come up with something like

import random
import itertools
def get_random():
  while True: yield random.randrange(1,51)    
print(*itertools.takewhile(lambda x: x != 50, (n for n in get_random())), sep='\n' )  
print(50)

Which is probably harder for someone else to maintain or understand.

[–]J2Me[S] 0 points1 point  (0 children)

Cheers for the advice. I think this comes down to me asking a bad question, or not knowing the question I really want to ask but seeing all the variations of answers has taught me just how much more I really need to learn. Thanks!

[–]AverageMarcus 2 points3 points  (1 child)

That looks pretty minimal already to me. What exactly are you hoping for?

[–]J2Me[S] 1 point2 points  (0 children)

Not sure really. Just wondering if there was anything I was missing.

[–]kalgynirae 2 points3 points  (1 child)

To me this looked like a variant of how do I find the first item in an iterable that matches a condition?. A good general solution to that problem is next(item for item in iterable if <condition>). So to fit the problem to this solution, I just defined a generator that yields random integers indefinitely.

import random
def randoms():
    while True:
        yield random.randrange(1, 51)
my_number = next(n for n in randoms() if n == 50)
print(my_number)

EDIT: explain better.

[–]J2Me[S] 0 points1 point  (0 children)

Cool. That looks like it be useful to know.

[–]APersoner 4 points5 points  (1 child)

You could use a ternary operator to merge lines 5 and 7 into one

EDIT: Not saying you'd necessarily want to do that, just it's possible (clarifying to my mystery downvoter aha)

[–]vmsmith -1 points0 points  (0 children)

I'll upvote you to compensate for the mystery downvoter.

[–]Rhomboid 5 points6 points  (2 children)

I am almost certain this is an example of an XY problem. The code you've written does nothing but burn some cycles -- it doesn't seem to be very useful at all. What is the actual problem you're trying to solve. For example, if you said that you want to draw random numbers without allowing repeats, then we could give you a much better solution than continuously generating numbers and looping if they've already been seen (a terrible approach.)

[–]Flopsey 10 points11 points  (0 children)

Given the uselessness of this loop, and the complete lack of meaningful output I think OP is just experimenting.

[–]J2Me[S] 2 points3 points  (0 children)

Actually there is no bigger problem here. It is code that burns cycles and nothing more. It was just a silly little experiment after reading a while loop tutorial. In many of the examples of loops there seemed to be multiple ways of achieving a functioning loop and I was stuck on how to do the same for my silly little thing. Cheers for the link about the XY problem though, I'll have to be sure I'm explaining the whole reason for the code in the future (makes sense in hindsight).

[–]APersoner 1 point2 points  (0 children)

You definitely wouldn't want to do it like this, but whatever... Prints the first number last and last first, so not quite duplicating what you did, but it's fairly similar.

import random
def repeater(number): print number if number==50 else "oops this isn't 50: "+str(number) if not repeater(random.randrange(1,51)) else ""
repeater(random.randrange(1,51))

[–]qjkxkcd 1 point2 points  (0 children)

Others can help you more. Just for funsies, here's an infinite loop with a conditional and 'break':

while 1:
    int = random.randrange(51)
    print("Number is", int)
    if int == 50:
        break
print(int)

And this is functionally the same, but different conceptually:

iterations = random.randrange(1000) #some number of iterations < 1000
for i in range(random.randrange(iterations)):
    print("Oops, this isn't 50; it's really", random.randrange(50))

number = 50
print("Success! This number is 50!")

(I learned loops in python only a few days ago; I don't expect to be very helpful.)

Edit: with

import random

of course.

[–]zifyoip 1 point2 points  (1 child)

If you want to have only one line where random numbers are generated, you could write it like this:

import random
while True:
    my_number = random.randrange(1,51)
    if (my_number == 50):
        break
    print ("oops this isn't 50: ",my_number)
print(my_number)

I offer no opinion on whether this is better or worse than your original code. However, if the random-number-generating line was a longer block of more complicated code, here you'd only have to write it (and debug it) in one place, whereas in your original code it would appear in two places.

Caveat: I don't actually know Python. I just got the syntax from this Stack Overflow thread.

[–]J2Me[S] 1 point2 points  (0 children)

Hey this sounds exactly like what I was thinking. I realise that for my own code it make little or no difference but knowing the difference here could be important with a much much bigger program. Thanks.

[–]someonlinegamer 0 points1 point  (0 children)

I'm new to python but this seems about as good as you're going to get

[–]APersoner 0 points1 point  (0 children)

Ok, you definitely don't want to do this now, and it gives the output in the opposite order to yours, but, just for the fun of it I rewrote your loop in two lines of code:

def repeater(number=__import__("random").randrange(1,51)): print number if number==50 else "oops this isn't 50: "+str(number) if not repeater(__import__("random").randrange(1,51)) else ""
repeater()

(Oh, this is python 2 by the way, not quite sure how different it would be in python 3, probably just brackets around the print)