C# 特定范围内的每个整数组合以及字符串列表

C# 特定范围内的每个整数组合以及字符串列表,c#,list,algorithm,C#,List,Algorithm,我有以下问题: 我有三个元素a,b和c。还有从0到100的整数。如何使所有可能的组合看起来像: a 0 b 0 c 0 a 1 b 0 c 0 a 0 b 1 c 0 a 0 b 0 c 1 a 1 b 1 c 0 ... a 100 b 100 c 100 等等?我正在使用C#,但我很难找到独立于编程语言的正确算法。不幸的是,我并不真正了解卡瑟斯产品等。你说你想了解 独立于编程语言找到正确的算法 因此,我将尝试使用最少的编程语言特性来回答这个问题。我将给出的示例假设编程语言具有可扩展的列表、

我有以下问题:

我有三个元素a,b和c。还有从0到100的整数。如何使所有可能的组合看起来像:

a 0 b 0 c 0
a 1 b 0 c 0
a 0 b 1 c 0
a 0 b 0 c 1
a 1 b 1 c 0
...
a 100 b 100 c 100
等等?我正在使用C#,但我很难找到独立于编程语言的正确算法。不幸的是,我并不真正了解卡瑟斯产品等。

你说你想了解

独立于编程语言找到正确的算法

因此,我将尝试使用最少的编程语言特性来回答这个问题。我将给出的示例假设编程语言具有可扩展的列表、数组、数组数组以及浅克隆数组的能力。这些是常见的编程特性,所以希望这一切都可以

要解决此问题,需要生成3组N个整数的所有组合,其中每个集合由0..N-1中的整数组成。(一组集合的组合集合——这就是所谓的集合——被称为这些集合的笛卡尔积。)

下面的解决方案使用递归,但我们不需要担心堆栈溢出,因为堆栈深度不超过要组合的集合数-在本例中为3。(通常对于递归,您会尝试使用堆栈类来管理它,但这会使代码更加复杂。)

工作原理:
combine()
递归地迭代每个集合的所有元素,并在每个递归级别开始处理下一个集合的元素

因此,递归的外部级别开始迭代集合[0]的所有元素,并为每个元素填充当前组合的下一项

然后:如果这是最后一组,则组合完成并输出。否则:进行递归调用以开始填充下一个集合中的元素

一旦我们有了所有的组合,我们就可以遍历它们并将它们分散 根据您的要求使用
a
b
c

综合起来:

using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
    class Program
    {
        static void Main()
        {
            var sets = createSets(3, 10);
            var combinations = Combinations(sets);

            foreach (var combination in combinations)
            {
                Console.WriteLine($"a {combination[0]} b {combination[1]} c {combination[2]}");
            }
        }

        static int[][] createSets(int numSets, int intsPerSet)
        {
            int[][] sets = new int[numSets][];

            // All the sets are the same, so we can just use copies of it rather than create multiples.
            int[] oneSet = new int[intsPerSet]; 

            for (int i = 0; i < intsPerSet; ++i)
                oneSet[i] = i;

            for (int i = 0; i < numSets; ++i)
                sets[i] = oneSet;

            return sets;
        }

        public static List<int[]> Combinations(int[][] sets)
        {
            var result = new List<int[]>();
            combine(sets, 0, new int[sets.Length], result);
            return result;
        }

        static void combine(int[][] sets, int set, int[] combination, List<int[]> output)
        {
            for (int i = 0; i < sets[set].Length; ++i)
            {
                combination[set] = sets[set][i];

                if (set < (sets.Length - 1))
                    combine(sets, set + 1, combination, output);
                else
                    output.Add((int[])combination.Clone());
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
名称空间控制台EAPP1
{
班级计划
{
静态void Main()
{
var集=createset(3,10);
var组合=组合(集合);
foreach(组合中的var组合)
{
WriteLine($“a{composition[0]}b{composition[1]}c{composition[2]}”);
}
}
静态int[][]创建集(int numSets,int intsPerSet)
{
int[][]集=新int[numSets][];
//所有的集合都是相同的,所以我们可以使用它的副本,而不是创建倍数。
int[]oneSet=newint[intsPerSet];
对于(int i=0;i
笔记
  • 这是一个低效的实现,因为它返回一个巨大列表中的所有组合。我保持这种方式是为了简单(并减少实现所需的程序语言特性的数量)。C#中的一个更好的解决方案是传入一个
    操作
    ,在每个组合中调用,这样结果就不需要通过一个庞大的列表返回
  • 这不会以与示例输出相同的顺序生成结果。我以为这没关系
  • 笛卡尔积的一个很好的Linq实现是。我强烈推荐你读它
    如果输出的顺序无关紧要,这就足够了:

    for(int i = 0; i <= 100; i++){
        for(int j = 0; j <= 100; j++){
            for(int k = 0; k <= 100; k++){
                Console.WriteLine($"a {i} b {j} c {k} ");
            }
        }
    }
    

    您是否尝试搜索文档和现有答案?似乎您希望循环这些列表的所有元素A、b和c始终位于同一位置,因此要生成所有结果,您基本上只需要给定整数中三个数字的所有组合:
    000
    (表示a0b0c0结果),
    001
    002
    ,…
    333
    var list=new[]{0,1,2,3};foreach(列表中的a)foreach(列表中的b)foreach(列表中的c){…}
    到目前为止您尝试了什么?给我们看一些代码和你卡住的地方。
    a 0 b 0 c 0 
    a 0 b 0 c 1 
    a 0 b 0 c 2 
    a 0 b 0 c 3 
    ...
    a 100 b 100 c 100