【问题标题】:Random distribution of boys and girls into groups c#将男孩和女孩随机分配到组c#
【发布时间】:2019-05-29 07:46:19
【问题描述】:

以前有人问过类似的问题,但没有以我可以使用的方式回答。

我有 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;
}

我希望这对你来说足够了,因为我为每个组都硬编码了它。
我感谢每一个想法,因为我接近绝望。

【问题讨论】:

  • 您的要求仍需澄清。尝试编辑您的问题并阐明您的需求。您的代码没有帮助。
  • 你怎么能用 50% 的男孩和 50% 的女孩来填充一组 3 人?
  • @DStanley 这是我的下一个问题
  • 你不能随机排列男孩名单和女孩名单,然后以交替的方式从每个名单中挑选一个吗? (顺便说一句,这也解决了上述问题)
  • 我假设奇数组会有更多的性别和更多的成员?例如如果男孩多于女孩,那么 3 人一组将是 (b,b,g),而 5 人一组将是 (b,b,b,g,g)?

标签: c# list math random


【解决方案1】:

查看代码中的 cmets 了解更多信息:

//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 使用“全球替代男孩/女孩”逻辑

【讨论】:

  • 我认为拥有一个全局计数器或确保每次都翻转只是在组内部更好,因为它会产生更均匀的分布。假设组大小为3,3,4。您编码的 AFAIU 将生成最后一组相同性别 (2+1, 2+1, 0+4),而不是更好的 2+1, 1+2, 2+2 分布。
【解决方案2】:

我会将它包含在包含您的 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多