提问人:John 提问时间:1/11/2012 最后编辑:CœurJohn 更新时间:9/5/2017 访问量:5576
如何获取字母数组的所有可能模式 [duplicate]
How to get every possible pattern of an array of letters [duplicate]
问:
可能的重复:
有没有更好的方法来进行字符串的排列?
假设我有字母
a、b、c、d
我想在一个 4 个字母长的字符串中获取这些字母的每一个可能的模式/组合。
AAAA的
巴阿
中国农业协会(CAAA)
达阿
阿巴
阿卡
阿卡德
阿爸
等等。
我可以使用什么循环或模式来列出每个可能的组合?
我是用 C# 编写的,但也欢迎使用 C++ 和 javascript 的示例。
我目前的想法是,每个字母可能增加一个字母。然后向右移动一次并重复。这不包括这样的模式。
阿爸
答:
这是一个只有一个 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 解决方案。无论如何,这些约束并不昂贵(只有 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"]
只是为了它,这里有一个通用的解决方案,用于 javascript 中任意数量的字母。
有趣的是,谷歌浏览器想翻译“马来语”的输出。
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 解决方案(用大括号调味):
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]);
使用 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
评论
使用递归、操作委托和 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();
}
}
}
评论
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());
}
这也可能会奏效;)
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));
评论
另一个基于 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"
创建一个重复四次的列表。 是一种非常通用的、多态的、moadic 操作,具有多种用途,其中包括生成列表列表的笛卡尔积。"abcd"
sequence
可以在 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 的灵感来自 Haskell 的 ,而 LINQ 的 是 Haskell 的 。from ... in
<-
select
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 论坛 in 项目 对于项目中的 B 对于 C in Items 对于 d in items]
你有一个有 2 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 = 22 × 4,所以你可以很容易地推广这个方案。
必须有一个 erlang 列表理解
类似的东西
Value = "abcd".
[ [A] ++ [B] ++ [C] ++ [D] || A <- Value, B <- Value, C <- Value, D <- Value ].
评论
RegEx