1

So I'm a python beginner and don't really know the gist of random functions. The following is my code (but only partially so it may not make sense but it has the point of what I wanted to ask. I put the conclusion of my code on the beginning of the paragraph after the code though. P.S. the code works):

if (1 <= numb_quiz <= 100):
    from openpyxl import Workbook, load_workbook
    book = load_workbook('Quiz_Problems.xlsx')
    read_sheet = book['100 Questions']
    length_row = read_sheet.max_row
    sheet = book.active

    numb_question = 1
    point = 0
    engagement = 0
    correct = 0
    while numb_question <= numb_quiz:
        randrow = random.randint(2, length_row)
        for row in read_sheet.iter_rows(randrow, randrow, min_col = 2, max_col = 2):
            print("")
            print("Question number", str(numb_question) + ":")   
            print([cell.value for cell in row]) 
            for col in read_sheet.iter_rows(min_row = randrow, max_row = randrow, min_col = 3, max_col = 3):
                print([cell.value for cell in col]) 
                break
            guest_answer = str(input("answer: "))
            answer = str("D"+str(randrow))
            correct_ans = sheet[answer].value

As you can see, to conclude what I wanted to do with the code above is to print random rows in column 3 with the random function from xslx file using python. The thing is, I wanted to prevent the random function to print the row from column 3 more than once in one run. Since again, I don't really understand what the 'import random' library can actually do, perhaps there is a way to get what I wanted. Does anyone have a solution? thank you so much

P.S. Since I'm a python beginner, I also would fancy an explanation from you (so not just the code. thank you!)

bin07
  • 33
  • 4
  • You said “I don't really understand what the 'import random' library can actually do”. If you’re going to make any headway as a programmer, searching for and reading [documentation](https://docs.python.org/3/library/random.html) is an essential skill. – pjs Oct 22 '22 at 17:22
  • Hi @pjs thank you for your suggestion. I actually don't have any plan to become a programmer ergo I don't fully read the documentation beforehand. However, I actually just know that reading documentation is essential, so thank you so much for that! I do have some interest to become a programmer in the future though! – bin07 Oct 22 '22 at 17:31
  • Does this answer your question? [How do I create a list of random numbers without duplicates](https://stackoverflow.com/questions/9755538/how-do-i-create-a-list-of-random-numbers-without-duplicates) – pjs Oct 22 '22 at 20:01

1 Answers1

1

So random just generates a number in that range you want. Computers don't generate numbers totally randomly. They use a "seed" to get started. If you pass the library the same seed each time (set it via random.seed(seedNo)), it will generate the same numbers in the same order. This can be useful for testing but also defeat the purpose of generating numbers. Therefore, a common practice is getting the current time of the system and using that as the seed.

Now for making sure you don't get the same question printed twice, I recommend you create a new empty list and each time you get a question, you add that index to the list. Then, put in a conditional checking if the index has come up before, and if it has, just pass (move on to the next iteration of the loop). The code might look like this:

askedAlready = []

    while numb_question <= numb_quiz:
        randrow = random.randint(2, length_row)
        if randrow in askedAlready: continue
        for row in read_sheet.iter_rows(randrow, randrow, min_col = 2, max_col = 2):
            print("")
            print("Question number", str(numb_question) + ":")   
            print([cell.value for cell in row]) 
            for col in read_sheet.iter_rows(min_row = randrow, max_row = randrow, min_col = 3, max_col = 3):
                print([cell.value for cell in col]) 
                break
            guest_answer = str(input("answer: "))
            answer = str("D"+str(randrow))
            correct_ans = sheet[answer].value
        askedAlready.append(randrow)

You could also rethink how you make the random generation. Make a list of all the possible question numbers then shuffle it. It won't have any duplicates. Then you could just iterate through the shuffled list. Note that this also uses the seeding concept in the same way (random.seed()) (Inspired by thefourtheye's answer: Generate 'n' unique random numbers within a range)

listOfRandRows = list(range(2,length_row))
random.shuffle(listOfRandRows) #this will shuffle the list "in place"
#then iterate
for i in listOfRandRows:
    #do your thing. i will be the row number randomly chosen

Edit per pjs's recommendation: shuffling is efficient enough but rejection can take a lot of extra time. Sample is better than rejection. It's described here: Generate 'n' unique random numbers within a range under Two-Bit Alchemist's answer

  • Hi, thank you so much for your answer and explanations! I've tried adding some of the codes that you've suggested, however, when I add the if randrow, the code does not run at all when it reach that point. Any suggestion? – bin07 Oct 22 '22 at 17:17
  • My bad! I added the append too early. Please try it with appending it after the conditional. I've edited my answer – Acetyl-CodeA Oct 22 '22 at 17:19
  • `random.sample()` would be far more efficient than your rejection scheme if the desired number of questions is a significant portion of the quiz pool. – pjs Oct 22 '22 at 17:29
  • Hi! @Acetyl-CodeA! thank you so much for yoru answer! so far it worked so well and I understand your explanation! – bin07 Oct 22 '22 at 17:32