Я новичок в 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
Решение
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."
Надеюсь, это помогло, мне понравилось работать над этим!
Проблема заключается в случайном выборе команды для каждого игрока. Поскольку 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)]
Используя только стандартную библиотеку, я бы решил это следующим образом:
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)
Вам нужно будет использовать набор для каждой группы, а затем выбрать случайную группу для человека. Как только каждая группа будет превышена, повторите, пока все группы не будут заполнены.
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.
Отрегулируйте вероятность каждой группы в соответствии с количеством групп. Используйте цикл while, который постоянно назначает группы и возвращается только после того, как группы имеют равную сумму.
Я бы сделал это с помощью 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]
divmod
для выполненияn % g
иn // g
в одной строке