【问题标题】:Combinations with missings与缺失的组合
【发布时间】:2015-01-20 23:37:00
【问题描述】:

所以我是 C# 新手,我有这个任务:

我有一份不明人数的名单(例如 5 人)。任务是获取列表中的人和他之后的人不能在同一组中的人的组。

前: 5人

{1},{2},{3},{4},{5},{1,3},{1,4},{1,5},{2,4},{2, 5},{3,5},{1,3,5}

我使用了链接中的组合方法 http://www.codeproject.com/Articles/26050/Permutations-Combinations-and-Variations-using-C-G 我有这个代码

private void button3_Click(object sender, EventArgs e)
    {
        outputBox.Clear();
        int nr = Convert.ToInt32(nmbrBox.Value);
        double tmp = Math.Pow(2, nr);
        double combs = tmp - 1;
        List<int> list = new List<int>();
        for (int i = 1; i <= nr; i++ )
        {
            list.Add(i);
        }

        outputBox.AppendText(combs.ToString() + " combinari\n\n");

        List<string> allCombinations = new List<String>();
        for (int i = 1; i <= list.Count; i++)
        {
            var combis = new Facet.Combinatorics.Combinations<int>(list, i, Facet.Combinatorics.GenerateOption.WithoutRepetition);
            allCombinations.AddRange(combis.Select(c => string.Join("", c)));
        }

        foreach (var combi in allCombinations)
        {            
            outputBox.AppendText(combi + "\n");
        }
    }

如何让它只显示我想要的结果?

【问题讨论】:

  • 你试过什么?您如何过滤组合以确定合法值?
  • 我已经尝试从“allCombinations”中获取组合,所以我可以使用变量并检查 number[i+1]=number[i]+1。

标签: c#


【解决方案1】:

我可以提供一个简单的解决方案。考虑到您的 group 字符串格式为“1 2 3”或“1”或“1 2”,所有组合中的 foreach 组使用如下验证方法:

public static bool IsGroupValid(string group)
{
    var indexes= group.Split(' ').Select(x=>Int32.Parse(x)).ToList();
    for (int i = 0; i < indexes.Count; i++)
    {
        if (indexes.Any(x=>x+1==indexes[i]))
            return false;
    }
    return true;
}

所以它看起来像这样:

foreach (var combi in allCombinations)
{        
    if(IsGroupValid(combi))    
        outputBox.AppendText(combi + "\n");
}

【讨论】:

  • 1. Parse 之后的 paranteses 太多(仅供参考) 2. 索引不会接受长度
  • 魅力十足!谢谢!很抱歉打扰了 :) 现在我知道我必须研究列表。
【解决方案2】:

您的问题是 Windows 窗体和一些组合代码的混合。在我的回答中,我将重点关注您问题的组合方面。您使用的库似乎非常好,但为了创建一个独立的答案,我决定创建自己的方法来生成组合。该实现以不利于性能的方式使用 LINQ 和递归,但只要您没有太多不应该成为问题的元素。

要创建给定长度的源序列的组合,请使用以下扩展方法(您必须将其放在 static class 中):

public static IEnumerable<IEnumerable<T>>  Combinations<T>(this IEnumerable<T> source, Int32 count)
  where T : IComparable<T> {
  if (count == 1)
    return source.Select(t => new T[] { t });
  return Combinations(source, count - 1)
    .SelectMany(
      values => source.Where(value => value.CompareTo(values.Last()) > 0),
      (values, value) => values.Concat(new T[] { value })
    );
}

如果输入是[1, 2, 3, 4, 5] 并且count 是4,那么输出是[1, 2, 3, 4], [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]

为了更容易确定组合是否有效,另一种扩展方法用于从序列创建元组:

public static IEnumerable<Tuple<T, T>> ToTuples<T>(this IEnumerable<T> source) {
  using (var enumerator = source.GetEnumerator()) {
    if (!enumerator.MoveNext())
      yield break;
    var lastValue = enumerator.Current;
    while (enumerator.MoveNext()) {
      yield return Tuple.Create(lastValue, enumerator.Current);
      lastValue = enumerator.Current;
    }
  }
} 

如果输入为[1, 2, 4, 5],则输出为[[1, 2], [2, 4], [4, 5]]

谓词用于确定给定组合是否有效。该组合被假定为一系列索引,因此两个连续的索引必须至少有 2 个部分才能有效:

Boolean IsValidCombination(IEnumerable<Int32> combination) {
  return combination
    .ToTuples()
    .All(tuple => tuple.Item2 - tuple.Item1 > 1);
}

现在你可以把它放在一起了。在这种情况下,输入是一个名称数组:

var people = new[] { "Arthur", "Bertha", "Cristobal", "Dolly", "Edouard" };
var indices = Enumerable.Range(0, people.Length);
var result = Enumerable
  .Range(1, people.Length - 1)
  .SelectMany(i => indices.Combinations(i))
  .Where(IsValidCombination)
  .Select(combination => combination.Select(i => people[i]));

这给出了以下结果:

亚瑟 伯莎 克里斯托瓦尔 多莉 爱德华 亚瑟,克里斯托瓦尔 亚瑟,多莉 亚瑟,爱德华 伯莎,多莉 伯莎,爱德华 克里斯托瓦尔,爱德华 亚瑟、克里斯托瓦尔、爱德华

【讨论】:

  • 感谢这个方法。我一定会检查一下 :) 我的方法遇到的问题是它会将答案存储在字符串 [] 中。所以如果我去 n = 30,它开始加载我的 RAM 超过 1.5Gb,导致我的应用程序冻结。我必须找到一种方法,找到它后立即显示结果,这样它就不会加载内存。
  • @CroveanVlad:如果元素太多,恐怕我的方法会出现性能问题。但是,组合是动态生成的,因此您可能会发现几乎没有使用任何内存,代价是 CPU 时间要求非常高。如果 n = 30,您可能需要一个非常具体的算法来避免使用过多的内存或 CPU。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
  • 2019-06-06
相关资源
最近更新 更多