Python даже групповое назначение

1

Я новичок в python и работал над генератором случайных команд. Проблема, с которой я столкнулся, заключается в том, что я не уверен, как заставить ее генерировать даже команды. Код ниже, а также образец вывода.

import random


def main():
    run = True
    while run:

        try:
            print("Welcome to this group picker, follow the instructions and your groups will be picked.")
            groupnum = int(input("How many groups do you want?"))
            peoplenum = int(input("How many people are there?"))
            print("Okay, assign everyone a number from 0 to", peoplenum - 1, ".")
            nums = []
            for i in range(0, peoplenum):
                nums.append(i)

            for i in nums:
                print("Number", i, "is in group", random.randint(1, groupnum))

            break

        except:
            print("Error, please follow instructions and enter only numbers.")
            break


main()

Пример вывода:

 Welcome to this group picker, follow the instructions and your groups
 will be picked.
 How many groups do you want?2 
 How many people are there?8
 Okay, assign everyone a number from 0 to 7 . 
 Number 0 is in group 1 
 Number 1 is in group 2 
 Number 2 is in group 1 
 Number 3 is in group 2 
 Number 4 is in group 1 
 Number 5 is in group 1 
 Number 6 is in group 2 
 Number 7 is in group 1
Теги:
random

6 ответов

0
Лучший ответ

Решение

import random


def main():
    run = True
    while run:

            print("\nWelcome to this group picker, follow the" \
                "instructions and your groups will be picked.\n")

            group_amount = int(input("How many groups do you want?\n"))
            people_amount = int(input("How many people are there?\n"))

            print("\nOkay, assign everyone a number from 1 to " +
                str(people_amount) + " .\n")

            group = list(range(0, group_amount))
            person = list(range(0, people_amount))
            group_size = people_amount / group_amount


            if group_size % 2 != 0:
                reg_group_size = (people_amount - 1) / group_amount
                odd_group_size = ((people_amount - 1) / group_amount) + 1

            for i in group[0:-1]:
               group[i] = reg_group_size

            group[-1] = odd_group_size

            for p in person:
                r = random.randint(0, len(group)-1)
                while group[r] == 0:
                    r = random.randint(0, len(group)-1) 
                person[p] = r + 1
                group[r] -= 1
                print("Person " + str(p + 1) + " is in group " + 
                    str(person[p]) + ".")

main()

Выход

(xenial)vash@localhost:~/pcc/12/alien_invasion_2$ python3 helping.py

Welcome to this group picker, follow theinstructions and your groups will be picked.

How many groups do you want?
3
How many people are there?
10

Okay, assign everyone a number from 1 to 10 .

Person 1 is in group 3.
Person 2 is in group 1.
Person 3 is in group 2.
Person 4 is in group 2.
Person 5 is in group 1.
Person 6 is in group 3.
Person 7 is in group 2.
Person 8 is in group 1.
Person 9 is in group 3.
Person 10 is in group 3.

Комментарии

Я согласен со всеми упомянутыми решениями, но я думаю, что большинство из них отклоняются довольно далеко от вашего исходного кода.

Я старался оставаться верным вашему коду при реализации недостающих частей, необходимых для того, чтобы заставить его функционировать по своему усмотрению и сохранить исходный результат.

Основная проблема заключалась в том, что значение random.randint не учитывает доступность пространства в каждой группе, уменьшающейся после того, как человеку назначена группа.

Шаг 1:

        group = list(range(0, group_amount))
        person = list(range(0, people_amount))
        group_size = people_amount / group_amount

Это создает group списков и person, размер которых соответствует их сумме. Кроме того, создайте group_size который даст нам количество person которые могут быть в каждой group.

Шаг 2:

        if group_size % 2 != 0:
            reg_group_size = (people_amount - 1) / group_amount
            odd_group_size = ((people_amount - 1) / group_amount) + 1

        for i in group[0:-1]:
           group[i] = reg_group_size

        group[-1] = odd_group_size

Здесь мы рассматриваем проблему, если у нас есть group неравного размера. Это создаст все group с равномерным размером, причем последняя group сможет удерживать левого person

Шаг 3:

        for p in person:
            r = random.randint(0, len(group)-1)
            while group[r] == 0:
                r = random.randint(0, len(group)-1) 
            person[p] = r + 1
            group[r] -= 1
            print("Person " + str(p + 1) + " is in group " + 
                str(person[p]) + ".")

Теперь самое интересное! Этот цикл назначит person[p] случайной group а затем уменьшит размер суммы этой group на 1.

Давайте сломаем его:

        for p in person:
            r = random.randint(0, len(group)-1)
            while group[r] == 0:
                r = random.randint(0, len(group)-1)

Мы собираемся пройти через person для всего населения, которого мы назначили. Затем мы выбираем случайную group для назначения person, но мы хотим убедиться, что group[r] имеет свободное пространство, while group[r] == 0: проверяет, есть ли место, если нет, новый r является пока мы не найдем случайную group, имеющую свободное пространство.

            person[p] = r + 1
            group[r] -= 1
            print("Person " + str(p + 1) + " is in group " + 
                str(person[p]) + ".")

Наконец, мы назначаем person[p] = r + 1 что дает person[p] номер group (используя r + 1 мы можем исключить "группу 0", так как списки начинаются с 0, а для презентации мы хотели бы начать с 1). После этого значение group[r] уменьшается на 1, что означает, что доступность пространства уменьшается. В заявлении на print снова + 1 просто так снова мы не называем кого-либо "Лицом 0."

Надеюсь, это помогло, мне понравилось работать над этим!

1

Проблема заключается в случайном выборе команды для каждого игрока. Поскольку random.randint производит одинаково распределенные значения, каждый игрок имеет одинаковые шансы быть назначенным для любой команды, поэтому вы можете оказаться в команде в одной команде.

Вместо этого вы должны рассмотреть возможность повторения команд и присвоение ему случайного игрока.

Плохое осуществление этой идеи будет похоже на

>>> import random
>>> 
>>> groupnum = 2
>>> peoplenum = 8
>>> 
>>> people = [i for i in range(peoplenum)]
>>> 
>>> for i in range(peoplenum):
...     group = i % groupnum
...     person = random.choice(people)
...     people.remove(person)
...     print('Number {} assigned to {}'.format(person, group))
... 
Number 6 assigned to 0
Number 7 assigned to 1
Number 4 assigned to 0
Number 3 assigned to 1
Number 2 assigned to 0
Number 5 assigned to 1
Number 1 assigned to 0
Number 0 assigned to 1

Это решит проблему, но она полагается на вызов remove чтобы избежать повторения членов команды. Чтобы этого избежать, вы можете перетасовать список игроков (делая его случайным) и zip результаты в списке команд.

>>> import random
>>>
>>> players = [i for i in range(peoplenum)]
>>> teams = [i for i in range(groupnum)]
>>> 
>>> random.shuffle(players)
>>> 
>>> [x for x in zip(players, teams)]
[(7, 0), (5, 1)]

Это явно не работает. Это связано с тем, что zip остановится, когда самый короткий итератор остановится, в наших groups. Мы хотим, чтобы он повторялся, пока есть игроки. Мы можем достичь такой функциональности с помощью itertools.cycle:

>>> import random
>>> import itertools
>>> 
>>> players = [i for i in range(peoplenum)]
>>> teams = itertools.cycle(range(groupnum))
>>> 
>>> random.shuffle(players)
>>> 
>>> [x for x in zip(players, teams)]
[(7, 0), (2, 1), (0, 0), (1, 1), (5, 0), (4, 1), (3, 0), (6, 1)]
1

Используя только стандартную библиотеку, я бы решил это следующим образом:

import random
from itertools import accumulate


def print_groups(n, g):
    # Prepare group separators
    size = n // g
    rem = n % g
    separators = list(accumulate([0] + [size+1] * rem + [size] * (g - rem)))

    # Make raw data
    items = list(range(n))
    random.shuffle(items)

    # Iterate and print
    for i, s in enumerate(zip(separators, separators[1:])):
        group = items[slice(*s)]
        print(f'Group {i+1}: {group} (size {len(group)})')

Если количество ваших людей делится на ваше количество групп, все группы будут иметь одинаковый размер, в противном случае первые группы n % g получат один дополнительный член.

Пример 1:

print_groups(12, 4)

Group 1: [6, 11, 10] (size 3)
Group 2: [7, 2, 5] (size 3)
Group 3: [3, 1, 9] (size 3)
Group 4: [4, 8, 0] (size 3)

Пример 2:

print_groups(14, 4)

Group 1: [8, 3, 4, 6] (size 4)
Group 2: [1, 11, 0, 12] (size 4)
Group 3: [7, 5, 9] (size 3)
Group 4: [13, 10, 2] (size 3)
  • 0
    Вы также можете использовать divmod для выполнения n % g и n // g в одной строке
0

Вам нужно будет использовать набор для каждой группы, а затем выбрать случайную группу для человека. Как только каждая группа будет превышена, повторите, пока все группы не будут заполнены.

import random
import sys


def main():
    while True:

        try:
            print("Welcome to this group picker, follow the instructions and your groups will be picked.")
            groupnum = int(input("How many groups do you want?"))
            peoplenum = int(input("How many people are there?"))
            if groupnum == 'Q':
                sys.exit(0)
            print("Okay, assign everyone a number from 1 to", peoplenum, ".")

            nums = []
            for i in range(1, peoplenum+1):
                nums.append(i)

            ''' Validate number of people vs groups '''
            if peoplenum % groupnum:
                print("error: You have incorrect number of people to divide them equally")
                sys.exit(1)

            ''' People per team '''
            peoplePerTeam = int(peoplenum/groupnum)

            ''' Initialize the group'''
            group = {}
            for i in range(1,groupnum+1):
                group[i] = set()

            ''' Loop through the people'''
            for person in nums:
                while True:
                    ''' Find random team '''
                    randomGroup = random.randint(1,groupnum)

                    ''' If team is not filled up yet, then add otherwise find a new team'''
                    if len(group[randomGroup]) < peoplePerTeam:
                        group[randomGroup].add(person)
                        break

            ''' Display the team info'''    
            for i in range(1,groupnum+1):
                print("Team %s members are %s" %(i, group[i]))

        except:
            print("Error, please follow instructions and enter only numbers.")
            break


main()

Пример выполнения этой программы приведен ниже:

Welcome to this group picker, follow the 
instructions and your groups will be picked.
How many groups do you want?2
How many people are there?8
Okay, assign everyone a number from 1 to 8 .
**Team 1 members are {1, 2, 5, 7}**
**Team 2 members are {8, 3, 4, 6}**
Welcome to this group picker, follow the 
instructions and your groups will be picked.
How many groups do you want?4
How many people are there?20
Okay, assign everyone a number from 1 to 20 .
**Team 1 members are {1, 18, 19, 20, 17}**
**Team 2 members are {16, 13, 11, 5, 7}**
**Team 3 members are {10, 9, 2, 3, 4}**
**Team 4 members are {8, 12, 15, 6, 14}**
Welcome to this group picker, follow the instructions and your groups will be picked.
0

Отрегулируйте вероятность каждой группы в соответствии с количеством групп. Используйте цикл while, который постоянно назначает группы и возвращается только после того, как группы имеют равную сумму.

0

Я бы сделал это с помощью numpy.random.choice, заменив значение false. См. Соответствующую документацию по количеству

Попробуйте сыграть с этим кодом:

import numpy as np

def assign_people_to_teams(people_count = 8, team_count = 2):
    """
        selects people_count random numbers in the range 0 to people_count-1 without replacement
        then make a team assignment decision based on desired number of teams.
    """
    return [
        element % team_count for element in list(
            np.random.choice(
                people_count,
                people_count,
                replace=False
            )
        )
    ]

team_assignment = assign_people_to_teams()

print(team_assignment)

Результат:

[0, 0, 1, 0, 0, 1, 1, 1]

Ещё вопросы

Сообщество Overcoder
Наверх
Меню