如何获得一系列字母的每种可能模式

时间:2012-01-10 21:58:45

标签: c# javascript algorithm

  

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

让我说我有字母

  

a b c d

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

  

aaaa

     

baaa

     

caaa

     

daaa

     

abaa

     

ACAA

     

acad

     

ABBA

等等。

我可以用什么循环或模式列出每种可能的组合?

我在C#中写这个,但是C ++和javascript中的例子也很受欢迎。

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

这样的模式
  

ABBA

15 个答案:

答案 0 :(得分:49)

您可以使用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

答案 1 :(得分:7)

这里只有一个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]);
                    }
                }
            }
        }

答案 2 :(得分:3)

只是为了它,这里是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>");
}

答案 3 :(得分:2)

递归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

答案 4 :(得分:1)

我使用递归来到这个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"]

答案 5 :(得分:1)

这也可能有效;)

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);

答案 6 :(得分:1)

任何给定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));

答案 7 :(得分:1)

你有一个带有2个 2 字母的字母,所以每个字母恰好表示两位,因此字母表示8位。现在,这是一个简单的枚举所有值的问题。在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 = 2 2×4 ,所以你可以很容易地推广这个方案。

答案 8 :(得分:0)

一个简单,直接的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]);

答案 9 :(得分:0)

使用递归,动作委托和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();
        }
    }
}

答案 10 :(得分:0)

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 :(得分:0)

另一个基于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)
      )
    )
  )
);

答案 12 :(得分:0)

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的<-,而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"

答案 13 :(得分:0)

在Python中:

items = [“a”,“b”,“c”,“d”]

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

答案 14 :(得分:0)

必须有一个erlang列表理解

这样的东西
Value = "abcd".
[ [A] ++ [B] ++ [C] ++ [D] || A <- Value, B <- Value, C <- Value, D <- Value ].