pythonrandomintegeryield

Python 3: using yield generator with random.randint to generate random integers in range (0-40) that do not duplicate for a range of 6


hi i am trying to use the yield generator to generate 6 random numbers that do not duplicate with the random modules random.randint function in a range of (0-40) this is most of the code for the program but not all of it to save space.

# Imports
from colorama import init, Fore
init()

# variables
cor = 0
no = 0
acceptable_values = list(range(0, 41))
acceptable_values_15 = list(range(0, 16))
unacceptable_values = list()
unacceptable_values2 = list()

    # user input for 6 non duplicate integers

    while True:
        try:
            user1 = int(input(Fore.LIGHTRED_EX + 'Input your first number between 0-40: ' + Fore.RESET))
            if user1 in acceptable_values:
                print(Fore.LIGHTGREEN_EX + '   Input accepted!' + Fore.RESET)
                unacceptable_values.append(user1)
                break
            else:
                print(Fore.LIGHTYELLOW_EX + '  Number entered must be between 0-40!' + Fore.RESET)
                continue
        except ValueError:
            print(Fore.LIGHTRED_EX + 'Invalid input!' + Fore.RESET)

(x6 for vars user1 though user6)


    # the 7th number is a lucky number between 0-15

    while True:
        try:
            user7 = int(input(Fore.LIGHTYELLOW_EX + 'Input your bonus seventh number between 0-15: ' + Fore.RESET))
            if user7 in unacceptable_values:
                print(Fore.LIGHTYELLOW_EX + "Input value has been entered before please select another number!" + Fore.RESET)
                continue
            elif user7 in acceptable_values_15:
                print(Fore.LIGHTGREEN_EX + '   Input accepted!' + Fore.RESET)
                break
            else:
                print(Fore.LIGHTYELLOW_EX + '  Number entered must be between 0-15!' + Fore.RESET)
                continue
        except ValueError:
            print(Fore.LIGHTRED_EX + 'Invalid input!' + Fore.RESET)

 # returns 6 random numbers between 0 and 40 with no duplicates. 

 def lottery():
        import random
        for i in range(6):
                yield random.randint(0, 41)
                unacceptable_values2.append(random_number)
                if random_number in unacceptable_values2:
                    continue

    # checks random numbers against user inputs 1-7 to see if they match and tallies the results

    for random_number in lottery():
        print(Fore.LIGHTCYAN_EX + "\nAnd the next number is... %d!" % random_number + Fore.RESET)

        if random_number == user1:
            print(Fore.LIGHTGREEN_EX + ' Input #1 number %s was correct!' % user1 + Fore.RESET)
            cor += 1
        elif random_number == user2:
            print(Fore.LIGHTGREEN_EX + ' Input #2 number %s was correct!' % user2 + Fore.RESET)
            cor += 1
        elif random_number == user3:
            print(Fore.LIGHTGREEN_EX + ' Input #3 number %s was correct!' % user3 + Fore.RESET)
            cor += 1
        elif random_number == user4:
            print(Fore.LIGHTGREEN_EX + ' Input #4 number %s was correct!' % user4 + Fore.RESET)
            cor += 1
        elif random_number == user5:
            print(Fore.LIGHTGREEN_EX + ' Input #5 number %s was correct!' % user5 + Fore.RESET)
            cor += 1
        elif random_number == user6:
            print(Fore.LIGHTGREEN_EX + ' Input #6 number %s was correct!' % user6 + Fore.RESET)
            cor += 1
        elif random_number == user7:
            print(Fore.LIGHTYELLOW_EX + ' Input #7 number %s was correct!' % user7 + Fore.RESET)
            cor += 1
        else:
            print(Fore.LIGHTRED_EX + ' None of your inputs match this selected number!' + Fore.RESET)
            no += 1

    # printing # of correct and wrong

    print(Fore.LIGHTGREEN_EX + '\n\nYou got %s numbers correct!' % cor + Fore.RESET)
    print(Fore.LIGHTRED_EX + '\nYou got %s numbers wrong!' % no + Fore.RESET)

the block of code i am having trouble with is this block:

 def lottery():
        import random

        # returns 6 numbers between 0 and 40 with no duplicates.

        for i in range(6):
                yield random.randint(0, 41)
                unacceptable_values2.append(random_number)
                if random_number in unacceptable_values2:
                    continue

I have several ideas as to what this code will actually do but i dont know what the actual outcome will be when a duplicate is found

my first guess is that the code will just generate 6 random numbers and display them regardless of if the number is a duplicate (not the desired outcome but probably the most likely outcome)

my second guess is that because of the continue it will just keep regenerating the 6 numbers if a duplicate is found until it gets 6 numbers with no duplicates and move on to the next block (desirable outcome but inefficient as it will keep regenerating all 6 number over and over until it has no duplicates)

my third guess is that it will generate random numbers tell it comes across a duplicate and simply regenerate that one duplicate number tell it is no longer a duplicate and then move to the next block (my desired outcome as it is probably the most efficient outcome but also an unlikely outcome)

my forth guess is that it will generate 6 numbers find a duplicate and discard it and continue leaving me a outcome with 5 random non repeating numbers instead of 6 (not a desired outcome as i need a range of 6 random non-duplicating numbers for this to work that being said i think this outcome is really unlikely as it probably wont discard the duplicate if found)

what i would like it to do is the third option where when it finds a duplicate number it just discards the duplicate and re-yields a new non-duplicate number in its place

i am trying to do this as readable as possible while using the yield function and random.randint without RE or partial or any convoluted methods as i want it to be as simple as possible for a friend who is new to python to easily be able to read and comprehend the code


Solution

  • random.sample() is ideal for this:

    import random
    
    def lottery():
        yield from random.sample(range(41), k=6)