【问题标题】:How to get every possible pattern of an array of letters [duplicate]如何获得字母数组的所有可能模式[重复]
【发布时间】:2012-02-07 07:52:00
【问题描述】:

可能重复:
Are there any better methods to do permutation of string?

假设我有字母

a b c d

我想在一个 4 个字母长的字符串中获取这些字母的每一个可能的模式/组合。

啊啊啊

caaa

哒哒

阿卡

学院派

阿爸

等等。

我可以使用什么循环或模式来列出所有可能的组合?

我是用 C# 编写的,但也欢迎使用 C++ 和 javascript 编写示例。

我目前的想法只为每个可能的字母增加一个字母。然后向右移动一次并重复。这不包括类似的模式。

阿爸

【问题讨论】:

  • 总是4个字母吗?如果是这样,那就很简单了。
  • @liho1eye 发布两个 for 循环毫无意义,因为它不是正确的解决方案。 @james 不,它可以超过 4 个字母,它的长度可以超过 4 个字母,所以这两个部分都是动态的。 @brian 你有什么比搜索旧帖子和发布维基百科链接更好的事情吗:T
  • 这与排列的问题不太一样。 { 'a', 'b', 'c', 'd' } 的排列不包括字符串“aaaa”。
  • @John - 通常它会帮助人们解决这样的简单问题。我实际上误读了您的问题,认为您正在寻找排列,因为这是一个常见的家庭作业问题,可以在这里发布。很抱歉 - 我没有意识到您在简单地计算 base4 时遇到了问题。
  • @John,您是否需要所有这些排列,或者您可以简单地使用RegEx 来验证您收到的文本格式是否正确?

标签: c# javascript algorithm


【解决方案1】:

必须有一个 erlang 列表理解

类似

Value = "abcd".
[ [A] ++ [B] ++ [C] ++ [D] || A <- Value, B <- Value, C <- Value, D <- Value ].

【讨论】:

    【解决方案2】:

    你有一个包含 22 个字母的字母表,所以每个字母正好表示两位,因此字母表示八位。现在,枚举所有值是一件简单的事情。在 pCeudocode 中:

    static const char alphabet[4] = { 'a', 'b', 'c', 'd' };
    
    for (unsigned int i = 0; i != 256; ++i)
    {
        for (unsigned int k = 0; k != 4; ++k)
        {
            print(alphabet[(i >> (2*k)) % 4]);
        }
    }
    

    这里是 256 = 22 × 4,所以你可以很容易地概括这个方案。

    【讨论】:

      【解决方案3】:

      在 Python 中:

      items = ["a", "b", "c", "d"]

      打印 [a + b + c+ d 对于一个项目 对于 b 在项目 对于 c 在项目 for d in items]

      【讨论】:

        【解决方案4】:

        Haskell 可能有最短的程序:

        sequence (replicate 4 "abcd")
        

        replicate 4 "abcd" 创建一个重复 "abcd" 四次的列表。 sequence 是一个非常通用的、多态的、moadic 操作,有很多用途,其中包括生成列表列表的笛卡尔积。

        可以用 C# 或其他 .NET 语言复制此解决方案。 Eric Lippert 的 LINQ 解决方案对应于这个 Haskell 解决方案:

        items = ["a", "b", "c", "d"]
        
        query = do i1 <- items
                   i2 <- items
                   i3 <- items
                   i4 <- items
                   return (i1 ++ i2 ++ i3 ++ i4)
        

        如果您比较它们,请注意 LINQ 的 from ... in 灵感来自 Haskell 的 &lt;-,而 LINQ 的 select 是 Haskell 的 return

        Haskell 单线解决方案与更长的解决方案之间的关系可以通过编写我们自己的sequence 定义来得出:

        sequence' [] = return []
        sequence' (m:ms) = do x <- m
                              xs <- sequence' ms
                              return (x:xs)
        

        在 LINQ 术语中,sequence 函数允许您将重复的 from ix in items 语句替换为仅用于选择每个项目的列表列表。

        编辑:一位朋友刚刚击败了我(嗯,除了import 之外的一行):

        import Control.Monad
        
        replicateM 4 "abcd"
        

        【讨论】:

          【解决方案5】:

          另一个基于 Linq 的答案:

          List<string> items = new List<string>() {"a", "b", "c", "d"};
          items.ForEach(i1 => 
            items.ForEach(i2 =>
              items.ForEach(i3 =>
                items.ForEach(i4 =>
                  Console.WriteLine(i1 + i2 + i3 + i4)
                )
              )
            )
          );
          

          【讨论】:

            【解决方案6】:

            对于任何给定的 n,LINQ 中的一个衬线:

                    var letters = new[] { "a", "b", "c", "d" };
                    int n = 4;
            
                    var z = Enumerable.Range(1, n)
                        .Select(x => letters.AsEnumerable())
                        .Aggregate((g,h) => g.Join(h, _ => true, _ => true, (a, b) => a + b));
            

            【讨论】:

            • 我编辑了 int n = 4;到 n = letters.length;
            【解决方案7】:

            这也可能会起作用;)

            var letters = new[] {'a','b','c','d'};
            Random random = new Random();
            HashSet<string> results = new HashSet<string>();
            
            while(results.Count < 256) {
                results.Add(letters[random.Next(4)] + letters[random.Next(4)]
                          + letters[random.Next(4)] + letters[random.Next(4)]);
            }
            
            results.ToList().ForEach(Console.WriteLine);
            

            【讨论】:

              【解决方案8】:

              您可以使用 LINQ 轻松做到这一点:

              string[] items = {"a", "b", "c", "d"};
              var query = from i1 in items
                          from i2 in items
                          from i3 in items
                          from i4 in items
                          select i1 + i2 + i3 + i4;
              
              foreach(var result in query)
                  Console.WriteLine(result);
              

              如果您事先不知道您想要四的组合,您可以通过更多的工作来计算任意笛卡尔积:

              http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx

              【讨论】:

                【解决方案9】:

                递归 C# 实现:

                public IEnumerable<string> CreateCombinations(IEnumerable<char> input, int length)
                {
                    foreach (var c in input)
                    {
                        if (length == 1)
                            yield return c.ToString();
                        else 
                        {
                            foreach (var s in CreateCombinations(input, length - 1))
                                yield return c.ToString() + s;
                        }
                    }
                }
                

                应该允许任意数量的字符和任意所需的字符串长度(直到堆栈溢出:))

                使用它:

                foreach (var s in CreateCombinations("abcd", 4))
                {
                    Console.WriteLine(s);
                }
                

                结果:

                aaaa
                aaab
                aaac
                aaad
                aaba
                aabb
                aabc
                aabd
                aaca
                ...
                dddd
                

                【讨论】:

                • 这是我会选择的答案。它很容易参数化笛卡尔积中的集合数量。没有那些丑陋的复制粘贴 for 循环。 :-)
                • 这正是我所需要的。 @ChrisWue - 你能帮我理解这是在做什么吗?我需要 Javascript 中的相同功能。
                【解决方案10】:

                C 中的实现

                #include <stdio.h>
                #define WORD_LEN 5
                #define ALPHA_LEN 4
                
                char alphabet[ALPHA_LEN] = {'a', 'b', 'c', 'd'};
                int w[WORD_LEN] = {};
                
                void print_word() {
                    int i;
                    char s[WORD_LEN + 1];
                    for(i = 0; i < WORD_LEN; i++) {
                        s[i] = alphabet[w[i]];
                    }
                    s[WORD_LEN] = '\0';
                    puts(s);
                }
                
                int increment_word() {
                    int i;
                    for(i = 0; i < WORD_LEN; i++) {
                        if(w[i] < ALPHA_LEN - 1) {
                            w[i]++;
                            return 1;
                        } else {
                            w[i] = 0;
                        }
                    }
                    return 0;
                }
                
                int main() {
                    int i;
                    do {
                        print_word();
                    } while (increment_word());
                }
                

                【讨论】:

                  【解决方案11】:

                  使用递归、Action Delegate 和 Lambdas!!! (只是为了好玩)

                  using System;
                  using System.Collections.Generic;
                  using System.Linq;
                  
                  namespace ConsoleApplication4
                  {
                      class Program
                      {
                          static void Main(string[] args)
                          {
                              List<char> letters = new List<char>() { 'a', 'b', 'c', 'd' };
                              List<string> words = new List<string>();
                              Action<IEnumerable<char>, string, List<string>> recursiveLetter = null;
                  
                              recursiveLetter = (availLetters, word, newWords) =>
                              {
                                  if (word.Length < availLetters.Count())
                                  {
                                      availLetters.ToList()
                                                  .ForEach(currentletter => 
                                                             recursiveLetter(availLetters, 
                                                                             word + currentletter, 
                                                                             newWords));
                                  }
                                  else
                                  {
                                      newWords.Add(word);
                                  }
                              };
                  
                              recursiveLetter(letters, string.Empty, words); // ALL THE MAGIC GO!
                  
                              words.ForEach(word => Console.WriteLine(word));
                              Console.ReadKey();
                          }
                      }
                  }
                  

                  【讨论】:

                  • 如果他想打印长度为 5 的 3 个或 4 个字母的所有组合怎么办?
                  • 易于更改,但不是 OP 想要的。
                  【解决方案12】:

                  这里只有一个 for 循环

                  var one = ['a','b','c','d'];
                  var length = one.length;
                  var total = Math.pow(length, length);
                  var pow3 = Math.pow(length,3);
                  var pow2 = Math.pow(length,2);
                  
                  for(var i = 0; i<total; i++)
                      console.log(one[Math.floor(i/pow3)], 
                          one[Math.floor(i/pow2)%length], 
                          one[Math.floor(i/length)%length], 
                          one[i%length]);
                  

                  这里有一个简单的低效方法:

                  var one = ['a','b','c','d'];
                  var i,j,k,l;
                  var len = 4;
                  for(i=0;i<len;i++) {
                      for(j=0;j<len;j++) {
                          for(k = 0; k < len; k++) {
                              for(l = 0; l<len; l++) {
                                  console.log(one[i], one[j], one[k], one[l]);
                              }
                          }
                      }
                  }
                  

                  类似的 C#:

                          var one = new[] {'a','b','c','d'};
                          var len = one.Length;
                  
                          for(var i=0;i<len;i++) {
                              for(var j=0;j<len;j++) {
                                  for(var k = 0; k < len; k++) {
                                      for(var l = 0; l<len; l++) {
                                          Console.Write(one[i] +  one[j] + one[k] +  one[l]);
                                      }
                                  }
                              }
                          }
                  

                  【讨论】:

                  • 这可以通过使用一个数组并引用不同的索引来完成。
                  • 你真的不需要 4 个数组吗?
                  • 有趣,好像可以,我只需要清理一下
                  【解决方案13】:

                  一个简单、直接的 javascript 解决方案(用大括号调味):

                  var letters = ['a', 'b', 'c', 'd'], len=letters.length;
                  
                  for (var i=len; i--;) 
                    for (var j=len; j--;) 
                      for (var k=len; k--;) 
                        for (var l=len; l--;) 
                          console.log (letters[i] + letters[j] + letters[k] + letters[l]);
                  

                  【讨论】:

                    【解决方案14】:

                    顺便说一句,这里有一个适用于 javascript 中任意数量字母的通用解决方案。

                    http://jsfiddle.net/U9ZkX/

                    有趣的是,谷歌浏览器想翻译“马来语”的输出。

                    var letters = ['a', 'b', 'c', 'd'];
                    var letterCount = letters.length;
                    var iterations = Math.pow(letterCount, letterCount);
                    
                    for (var i = 0; i < iterations; i++) {
                        var word = "";
                    
                        for (var j = 0; j < letterCount; j++) {
                            word += letters[Math.floor(i / Math.pow(letterCount, j)) % letterCount];
                        }
                    
                        document.write(word + "<br>");
                    }
                    

                    【讨论】:

                      【解决方案15】:

                      我来到这个使用递归的 javascript 解决方案。无论如何,这些限制并不昂贵(只有 4^4 次调用)

                      (function() {
                         var combinations = [];
                      
                         (function r(s) {
                             s = s || '';
                             if (s.length === 4) {
                                combinations[combinations.length] = s;
                                return;
                             }
                             r(s + 'a');
                             r(s + 'b');
                             r(s + 'c');
                             r(s + 'd');
                      
                         })();
                      
                         console.log(combinations);
                      })();
                      

                      输出是

                      ["aaaa", "aaab", "aaac", "aaad",...., "dddc", "dddd"]
                      

                      【讨论】:

                        猜你喜欢
                        • 2012-12-03
                        • 1970-01-01
                        • 2019-06-26
                        • 2019-10-14
                        • 1970-01-01
                        • 2012-06-05
                        • 2022-11-29
                        相关资源
                        最近更新 更多