0

Ok so I have spent hours trying to resolve this and I feel its some simple error but I cannot find a way to resolve this. the section I am having issues with is the second half of the code. There seems to be an infinite loop somewhere among the 2 nested while loops. If anyone is able to help, this would be great, thanks in advance.

import sympy as sym
import random

A, B, C, D, E, F, G, H, I, J = sym.symbols('A, B, C, D, E, F, G, H, I, J')
picks_a_person = [A, B, C, D, E, F, G, H, I, J] #List of people picking a name from a hat
person_gets_picked = [A, B, C, D, E, F, G, H, I, J] # List of names drawn from a hat
def re_draws(p):
    n = 0
    count = 0
    while n < 1000: #Repeats the test 1000 times for an accurate percentage
        n += 1
        random.shuffle(person_gets_picked) #Chooses a random order of the list of names drawn
        for i in range(p):
            if person_gets_picked[i] == picks_a_person[i]: #Checks for all 'p' elements of the lists are different
                count = count + 1
    print("count = " + str(count)) #Returns the number of times a re-draw was not required

import numpy as np
from collections import Counter

total = []
while len(total) < 1000:
    order = []
    picks_a_person = [A, B, C, D, E, F, G, H, I, J]
    person_gets_picked = [A, B, C, D, E, F, G, H, I, J]
    while len(order) < 10:
        a = person_gets_picked[random.randint(0, (len(person_gets_picked)-1))]
        if a != picks_a_person[0]:
            order.append(a)
            person_gets_picked.remove(a)
            del picks_a_person[0]
    total.append(order)
Counter(np.array(total)[:,1])
1
  • 1
    put print(...) to whatever you are trying to decrease for debugging. for example len(order) Commented Dec 13, 2017 at 22:51

1 Answer 1

2

While there are a lot of odd things about your code, this is where it gets into an infinite loop:

picks_a_person = [A, B, C, D, E, F, G, H, I, J]
person_gets_picked = [A, B, C, D, E, F, G, H, I, J]
while len(order) < 10:
    a = person_gets_picked[random.randint(0, (len(person_gets_picked)-1))]
    if a != picks_a_person[0]:
        order.append(a)
        person_gets_picked.remove(a)
        del picks_a_person[0]
total.append(order)

Let's do some rubber duck debugging - what happens when your random.randint(0, (len(person_gets_picked)-1)) returns a number larger than 0 nine times in a row (worst case scenario)? All person_gets_picked elements except A get removed and added to the order list (which is still under 10 elements to break away from the while loop).

At that point we have a state as picks_a_person = [A] and person_gets_picked = [A]. random.randint(0, (len(person_gets_picked)-1)) will, thus, always return 0, a will always be set to A and since picks_a_person[0] == A the condition if a != picks_a_person[0] will never be evaluated as True, hence the order will never get its 10th element and therefore you got yourself an infinite loop.

It doesn't even have to be nine positive numbers in a row for this to occur - all it needs to happen is for A to remain as one of the last two picks and for random to land on the other option.

So why don't you write your whole loop as:

persons = [A, B, C, D, E, F, G, H, I, J]
persons_num = len(persons)
total = [random.sample(persons, persons_num) for _ in range(1000)]

And you're done.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.