C# 两个字符的组合

C# 两个字符的组合,c#,combinations,C#,Combinations,我把输入设为int,根据这个输入,我想要两个字符的组合, 例如 我把输入设为2,我有两个字符x和y,所以我想要这样的组合 xx,yy,xy,yx 如果输入是3,我想要 xxx,xyy,xxy,xyx,yxx,yyy,yxy.yyx 等等,我尝试了以下代码 int input1 = 4; Double totalpossibilities = Math.Pow(2, input1); string[] PArray = new stri

我把输入设为int,根据这个输入,我想要两个字符的组合, 例如 我把输入设为2,我有两个字符x和y,所以我想要这样的组合

    xx,yy,xy,yx
如果输入是3,我想要

    xxx,xyy,xxy,xyx,yxx,yyy,yxy.yyx
等等,我尝试了以下代码

     int input1 = 4;
        Double totalpossibilities = Math.Pow(2, input1);
        string[] PArray = new string[Convert.ToInt16(totalpossibilities)];
        char[] chars = new char[] { 'x', 'y'};

        for (int i = 0; i < totalpossibilities; i++)
        {
            string possibility = "" ;
            for (int j = 0; j < input1; j++)
            {
                Random random = new Random();
                int r = random.Next(chars.Length);
                char randomChar = chars[r];
                possibility = possibility + randomChar;

            }
            if (PArray.Contains(possibility))
            {
                i--;
            }
            else
                PArray[i] = possibility;
        }

但正如您所看到的,我使用的是随机函数,所以我需要花费太长的时间来完成,是否有任何不同的逻辑?

您可以运行一个从0到0的for循环。 例如,将i转换为二进制,在迭代20时,这将导致10100。 填充结果以输入1个字符,例如8个位置:0000100 然后转换为字符串,用x替换所有零,用y替换所有1

        int places = 4;
        Double totalpossibilities = Math.Pow(2, places);

        for (int i = 0; i < totalpossibilities; i++)
        {
            string CurrentNumberBinary = Convert.ToString(i, 2).PadLeft(places, '0');

            CurrentNumberBinary = CurrentNumberBinary.Replace('0', 'x');
            CurrentNumberBinary = CurrentNumberBinary.Replace('1', 'y');
            Debug.WriteLine(CurrentNumberBinary);
        }

您可以运行从0到0的for循环。 例如,将i转换为二进制,在迭代20时,这将导致10100。 填充结果以输入1个字符,例如8个位置:0000100 然后转换为字符串,用x替换所有零,用y替换所有1

        int places = 4;
        Double totalpossibilities = Math.Pow(2, places);

        for (int i = 0; i < totalpossibilities; i++)
        {
            string CurrentNumberBinary = Convert.ToString(i, 2).PadLeft(places, '0');

            CurrentNumberBinary = CurrentNumberBinary.Replace('0', 'x');
            CurrentNumberBinary = CurrentNumberBinary.Replace('1', 'y');
            Debug.WriteLine(CurrentNumberBinary);
        }

使用笛卡尔乘积扩展方法的副本逐字复制自:

然后,在您的代码中可以有:

IEnumerable<char> possibleCharacters = "xy";//change to whatever
int numberOfDigits = 3;

var result = Enumerable.Repeat(possibleCharacters, numberOfDigits)
     .CartesianProduct()
     .Select(chars => new string(chars.ToArray()));

//display (or do whatever with) the results
foreach (var item in result)
{
    Console.WriteLine(item);
}

使用笛卡尔乘积扩展方法的副本逐字复制自:

然后,在您的代码中可以有:

IEnumerable<char> possibleCharacters = "xy";//change to whatever
int numberOfDigits = 3;

var result = Enumerable.Repeat(possibleCharacters, numberOfDigits)
     .CartesianProduct()
     .Select(chars => new string(chars.ToArray()));

//display (or do whatever with) the results
foreach (var item in result)
{
    Console.WriteLine(item);
}

如果你总是有两个字符,那么最简单的方法就是使用整数的组合性质。如果采用从2^n到2^n+1-1的所有数字的二进制形式,您会注意到它表示长度为n的“0”和“1”的所有可能组合:


对于2个以上的字符,我将使用类似的方法,但基数不同。

如果总是有2个字符,那么最简单的方法就是使用整数组合性质。如果采用从2^n到2^n+1-1的所有数字的二进制形式,您会注意到它表示长度为n的“0”和“1”的所有可能组合:

对于超过2个字符,我将使用类似的方法,但基础不同。

下面是一个列表解决方案。推广到任意数量的字母

static List<string> letters = new List<string> { "x", "y", };

static List<string> MakeList(int input)
{
  if (input < 0)
    throw new ArgumentOutOfRangeException();

  var li = new List<string> { "", };

  for (int i = 0; i < input; ++i)
    li = Multiply(li);

  return li;
}

static List<string> Multiply(List<string> origList)
{
  var resultList = new List<string>(origList.Count * letters.Count);
  foreach (var letter in letters)
    resultList.AddRange(origList.Select(s => letter + s));
  return resultList;
}
这里有一个列表解决方案。推广到任意数量的字母

static List<string> letters = new List<string> { "x", "y", };

static List<string> MakeList(int input)
{
  if (input < 0)
    throw new ArgumentOutOfRangeException();

  var li = new List<string> { "", };

  for (int i = 0; i < input; ++i)
    li = Multiply(li);

  return li;
}

static List<string> Multiply(List<string> origList)
{
  var resultList = new List<string>(origList.Count * letters.Count);
  foreach (var letter in letters)
    resultList.AddRange(origList.Select(s => letter + s));
  return resultList;
}

svenv-answer是对这个问题的正确且非常聪明的答案,但我认为我应该提供一个通用的解决方案来生成一组令牌的所有排列,这可能对其他可能有类似问题的人有用

public class Permutations
{
    public static string[][] GenerateAllPermutations(string[] tokens, int depth)
    {
        string[][] permutations = new string[depth][];

        permutations[0] = tokens;

        for (int i = 1; i < depth; i++)
        {
            string[] parent = permutations[i - 1];
            string[] current = new string[parent.Length * tokens.Length];

            for (int parentNdx = 0; parentNdx < parent.Length; parentNdx++)
                for (int tokenNdx = 0; tokenNdx < tokens.Length; tokenNdx++)
                    current[parentNdx * tokens.Length + tokenNdx] = parent[parentNdx] + tokens[tokenNdx];

            permutations[i] = current;
        }

        return permutations;
    }

    public static void Test()
    {
        string[] tokens = new string[] { "x", "y", "z" };
        int depth = 4;

        string[][] permutations = GenerateAllPermutations(tokens, depth);

        for (int i = 0; i < depth; i++)
        {
            foreach (string s in permutations[i])
                Console.WriteLine(s);

            Console.WriteLine(string.Format("Total permutations:  {0}", permutations[i].Length));
            Console.ReadKey();
        }
    }
}

干杯,

svenv答案是这个问题的正确且非常聪明的答案,但我想我会提供一个通用的解决方案来生成一组令牌的所有排列,这可能对其他可能有类似问题的人有用

public class Permutations
{
    public static string[][] GenerateAllPermutations(string[] tokens, int depth)
    {
        string[][] permutations = new string[depth][];

        permutations[0] = tokens;

        for (int i = 1; i < depth; i++)
        {
            string[] parent = permutations[i - 1];
            string[] current = new string[parent.Length * tokens.Length];

            for (int parentNdx = 0; parentNdx < parent.Length; parentNdx++)
                for (int tokenNdx = 0; tokenNdx < tokens.Length; tokenNdx++)
                    current[parentNdx * tokens.Length + tokenNdx] = parent[parentNdx] + tokens[tokenNdx];

            permutations[i] = current;
        }

        return permutations;
    }

    public static void Test()
    {
        string[] tokens = new string[] { "x", "y", "z" };
        int depth = 4;

        string[][] permutations = GenerateAllPermutations(tokens, depth);

        for (int i = 0; i < depth; i++)
        {
            foreach (string s in permutations[i])
                Console.WriteLine(s);

            Console.WriteLine(string.Format("Total permutations:  {0}", permutations[i].Length));
            Console.ReadKey();
        }
    }
}


干杯,

试着将随机数的初始化提取到程序的开头……或者你希望每次迭代都有一个新的种子吗?他根本不应该使用随机数来解决这个问题。@Magnus我知道我不应该使用随机数,但是有没有办法获得排列?你能帮帮忙吗?@Hiren,Servy给了你一个很好的答案。试着将random的初始化提取到程序的开头……或者你希望每次迭代都有一个新的种子吗?他根本不应该使用random来解决这个问题。@Magnus我知道我不应该使用random,但是有什么方法可以得到排列吗?你能帮忙吗?@Hiren,Servy为您提供了一个很好的答案。我理解,但我不想使用随机函数,因为假设输入为200,则需要很长时间才能完成。可能的字符串数为2^n。你一生中能解决的最大输入可能少于32。有趣的解决方案。但由于Convert.ToStringInt32不适用于三元、四元等。它不适用于三、四等字母。我写了另一个解决方案。我明白,但我不想使用随机函数,因为假设输入是200,它需要很长时间才能完成。可能的字符串数是2^n。你一生中能解决的最大输入可能少于32。有趣的解决方案。但由于Convert.ToStringInt32不适用于三元、四元等。它不适用于三、四等字母。我编写了另一个解决方案。在末尾添加了一个Select,这样您就可以对字符串进行枚举,这可能更容易处理。如果您希望对字符进行枚举,则可以删除结尾处的选择。是否需要对此代码进行任何更改?我使用了相同的代码,但在var result=Enumerable.RepeatpossibleCharacters,numberOfDigits.CartesianProduct.Selectchars=>new stringchars.ToArray中出错;不包含“笛卡尔乘积”的定义笛卡尔乘积方法需要在静态类中,因为它是一个扩展方法。如果您愿意,也可以将其重构为常规静态方法。我接受svenv的答案,但也会更新您的答案,感谢您的帮助在末尾添加了一个Select,这样您就有了字符串枚举,这对您来说可能更容易处理。如果希望有字符枚举的枚举,可以删除末尾的选择
s、 我是否需要更改此代码?我使用了相同的代码,但在var result=Enumerable.RepeatpossibleCharacters,numberOfDigits.CartesianProduct.Selectchars=>new stringchars.ToArray中出错;不包含“笛卡尔乘积”的定义笛卡尔乘积方法需要在静态类中,因为它是一个扩展方法。如果你愿意的话,你也可以把它重构成一个普通的静态方法。我接受svenv的答案,但也支持你的答案,谢谢你的帮助