In [ ]:
import random

In [ ]:
def generateRandomPerson(level=0, new=True):
    score = 0
    sex = random.choice(['man', 'woman'])
    if sex=='man':
        score = random.normalvariate(50, 10) + 2.01
    else:
        score = random.normalvariate(50, 10)
    return {
        'sex': sex,
        'score': score,
        'level': level,
        'new': new
    }
print(generateRandomPerson())

In [ ]:
def generateStaff(levels):
    staff = []
    for idx, level in enumerate(levels):
        staff.append([generateRandomPerson(level=idx, new=False) for person in range(level)])
    return staff

In [ ]:
def allAreNew(staff):
    for level in staff:
        for employee in level:
            if not employee['new']:
                return False
    return True

In [ ]:
def quit(staff, attrition):
    for idx, level in enumerate(staff):
        for idx2, employee in enumerate(level):
            rn = random.random()
            if rn <= attrition:
                staff[idx][idx2] = None
    return staff

In [ ]:
def pickBest(level):
    best = None
    bestidx = None
    for idx, employee in enumerate(level):
        if best is None or (employee is not None and employee['score'] > best['score']):
            best = employee
            bestidx = idx
    return bestidx

In [ ]:
def promote(staff):
    for level in reversed(list(range(len(staff)))):
        newlevel = []
        for idx, employee in enumerate(staff[level]):
            if employee is None:
                if (level > 0):
                    bestidx = pickBest(staff[level - 1])
                    promotedemployee = staff[level - 1][bestidx]
                    promotedemployee['level'] = level
                    staff[level - 1][bestidx] = None
                    newlevel.append(promotedemployee)
                else:
                    newlevel.append(generateRandomPerson())
            else:
                newlevel.append(employee)
        staff[level] = newlevel
    return staff

In [ ]:
def mfratio(level):
    m = 0
    f = 0
    for employee in level:
        if employee['sex'] == 'man':
            m += 1
        else:
            f += 1
    return m, f, m/float(m + f), f/float(m+ f)

In [ ]:
levels = [500, 350, 200, 150, 100, 75, 40, 10]
attrition = 0.15
staff = generateStaff(levels)
# quit/promotion cycle until all employees are new
while not allAreNew(staff):
    staff =quit(staff, attrition)
    staff = promote(staff)
# print results
for level in staff:
    print(mfratio(level))

In [ ]:
print(staff[-1])

In [ ]: