Случайное распределение мальчиков и девочек по группам c # - PullRequest
0 голосов
/ 02 января 2019

Подобные вопросы задавались ранее, но я не ответил так, как я могу с ними работать.

У меня есть группы по 3, 4, 5 и 6, и в каждой группе должно быть 50% мальчиков и 50% девочек. Пользователь определяет количество каждой группы, а также количество мальчиков и девочек.

Например: 12 девочек, 15 мальчиков, 1 * 3, 2 * 4, 2 * 5 и 1 * 6 групп.

У меня уже есть экземпляр Random. Как теперь я могу равномерно распределить случайно выбранных мальчиков / девочек по группам?

Случайно для мальчиков и группы из 4 человек:

//for each group of 4
for (int i = 0; i < tischgruppenVierer; i++)
{
    //only do this two times because 50% boys
    for (int j = 0; j < 4/2; j++)
    {
        var picked = namesBoys[random.Next(0, namesBoys.Count())];
        namesBoys.Remove(picked); //no duplicates
        picked = new TischVier().student;
    }
}

и класс TischVier:

public class TischVier
{
    public string student;
}

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

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Я бы обернул это в классе, содержащем ваши 2 списка (юноши и девушки) вместе с методом, чтобы получить группу указанного размера. В псевдокоде этот метод идет:

  1. Перемешать список мальчиков и список девочек
  2. Инициализировать логический переключатель для переключения между мальчиками и девочками
  3. Подсчитайте до необходимого размера для каждой итерации ....
  4. Вычеркнуть мальчика или девочку из списка в соответствии с логическим флагом
  5. Отразить логическое значение

В реальном коде это выглядит примерно так:

public IEnumerable<string> GetGroup(int size)
{
    Shuffle(boys);
    Shuffle(girls);
    if((boys.Count + girls.Count) < size)
    {
            throw new ArgumentException("Not enough people to satisfy group");
    }
    bool isBoy = rng.NextDouble() > 0.5;
    for(var i = 0;i<size;i++)
    {
        string next = "";
        if(isBoy)
        {
            yield return PopBoy();
        }
        else
        {
            yield return PopGirl();
        }
        isBoy = !isBoy;
    }
}

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

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

private string PopBoy()
{
    if(boys.Count>0)
    {
        var name = boys[0];
        boys.RemoveAt(0);
        return name;
    }
    else
    {
        return PopGirl();
    }
}
private string PopGirl()
{
    if(girls.Count>0)
    {
        var name = girls[0];
        girls.RemoveAt(0);
        return name;
    }
    else
    {
        return PopBoy();
    }
}

Полностью рабочий код можно найти здесь: https://rextester.com/DKYCMN49734

0 голосов
/ 02 января 2019

См. Комментарии в коде для получения дополнительной информации:

//setup

//hold the group sizes we want to make - you say your user chose this
int[] groupSizes = new[] {3, 4, 4, 5, 5, 6};

//you have lists of people from somewhere
List<Person> boys = new List<Person>();
for(int i = 0; i < 15; i++)
  boys.Add(new Person());
List<Person> girls = new List<Person>();
for(int i = 0; i < 12; i++)
  girls.Add(new Person());

//logic of random grouping
List<List<Person>> groups = new List<List<Person>>();
Random r = new Random();

bool takeBoy = false;

//for each groupsize we make
foreach(int g in groupSizes){ 

  List<Person> group = new List<Person>(); //new group
  for(int i = 0; i < g; i++){ //take people, up to group size

    //take boys and girls alternately
    takeBoy = !takeBoy;
    var fr = takeBoy ? boys : girls;

    //if there are no more boys/girls, take other gender instead
    if(fr.Count == 0) 
      fr = takeBoy ? girls : boys;

    //choose a person at random, less than list length
    var ri = r.Next(fr.Count);

    //add to the current grouping
    group.Add(fr[ri]);

    //remove from consideration
    fr.RemoveAt(ri);
  }
  //group is made, store in the groups list
  groups.Add(group);
}

И демонстрационная скрипка: https://dotnetfiddle.net/KS7HFb с использованием логики «всегда бери мальчика первым»

Еще одна демонстрационная скрипка: https://dotnetfiddle.net/68YFYf с использованием логики "глобального альтернативного взятия мальчика / девочки"

...