如何获取字母数组的每个可能模式

How to get every possible pattern of an array of letters

本文关键字:模式 数组 何获取 获取      更新时间:2023-09-26

可能的重复项:
有没有更好的方法来排列字符串?

假设我有字母

阿 b c d

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

AAAA

巴阿

华促会

哒��

阿巴

卡阿

阿卡德

阿爸

等等。

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

我用 C# 编写本文,但也欢迎 C++ 和 javascript 中的示例。

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

阿爸

使用 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

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

只是为了它,这里有一个通用的解决方案,适用于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>");
}

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

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

这可能也行得通,;)

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

LINQ 中任何给定 n 的一个行:

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

你有一个包含 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 = 22 ×  4,因此您可以轻松地推广此方案。

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

使用递归、操作委托和 lambda!! (只是为了好玩(

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

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

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

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"

在 Python 中:

项目 = ["a", "b", ">

c", "d"]

打印 [a + b + c+ d 对于 a 在项目中 对于项目中的 B 对于项目中的 C 对于项目中的 d]

必须有一个 erlang 列表理解

类似的东西

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