我搜索了stackoverflow和网页上的类似问题,但我找不到我需要的解决方案。
我正在编写代码列表生成器。
所以例如我有一个像List<char> { 'a', 'b', 'c' };
这样的字符列表。
我有一些设置,例如(int)minLength
2
和(int)maxLength
3
。
我想要这个输出:
aa
ab
ac
ba
bb
bc
ca
cb
cc
aaa
aab
aac
aba
abb
abc
aca
acb
acc
baa
bab
bac
bba
bbb
bbc
bca
bcb
bcc
caa
cab
cac
cba
cbb
cbc
cca
ccb
ccc
在gereral中,我只会创建多维循环,但由于minLength,maxLength&amp; charList值。
所以我选择了一个像这个例子的“自我调用函数”:
private void loop() {
for( int i = 0; i < num; i++ ) {
// stuff
loop();
}
}
到目前为止,我已经制作了一堆代码,但是在这个阶段我被卡住了......:
Thread mainThread;
List<char> azlower;
List<char> azupper;
List<char> nullnine;
List<char> totalChars;
int totalNum;
int levelCounter;
bool running;
public Form1() {
InitializeComponent();
}
private void init() {
azlower = new List<char> { 'a', 'b', 'c' , 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
azupper = new List<char> { 'A', 'B', 'C' , 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
nullnine = new List<char> { '0', '1', '2' /* , '3', '4', '5', '6', '7', '8', '9' */ };
totalChars = new List<char> ();
running = false;
}
private void button1_Click( object sender, EventArgs e ) {
if( !running ) {
init();
// Start
if( checkBoxAZ1.Checked ) {
foreach( char character in azlower ) {
totalChars.Add( character );
}
}
if( checkBoxAZ2.Checked ) {
foreach( char character in azupper ) {
totalChars.Add( character );
}
}
if( checkBox09.Checked ) {
foreach( char character in nullnine ) {
totalChars.Add( character );
}
}
if( checkBoxS.Checked && textBoxSpec.Text != "" ) {
char[] specArray = textBoxSpec.Text.ToCharArray();
foreach( char character in specArray ) {
totalChars.Add( character );
}
}
totalNum = totalChars.Count;
levelCounter = Int32.Parse( textBoxMinLength.Text );
mainThread = new Thread( new ThreadStart( run ) );
button1.Text = "Stop";
running = true;
mainThread.Start();
} else {
mainThread.Abort();
button1.Text = "Start";
running = false;
}
}
private void run() {
for( int i = 0; i < totalNum; i++ ) {
Invoke( ( MethodInvoker ) delegate {
write( totalChars[ i ].ToString() );
if( i == totalNum - 1 && levelCounter == Int32.Parse( textBoxMaxLength.Text ) ) {
write( "\n" );
}
} );
if( levelCounter < Int32.Parse( textBoxMaxLength.Text ) ) {
levelCounter++;
run();
}
}
return;
}
private void write( string line ) {
richTextBox1.Text += line;
}
但是通过上面的设置和我的代码,输出看起来像这样:
aabc
bc
我认为我只是犯了一个思维错误,不是吗?
那么伙计们,你对我有什么建议吗?我也看过笛卡尔积,但我认为它只适用于一个阵列......
这是任何帮助。答案 0 :(得分:1)
以下是使用递归生成它的示例。
IEnumerable<string> GenerateCode(int length, int min, IEnumerable<char> chars)
{
if (length == 0)
{
yield return string.Empty;
yield break;
}
foreach (var mid in GenerateCode(length - 1, min, chars))
{
foreach (var c in chars)
{
var t = mid + c;
if (length >= min)
Console.WriteLine(t); // replace with where you want to put the results
yield return t;
}
}
}
// now call this method:
GenerateCode(3 /*max length*/, 2 /*min length*/, new [] { 'a', 'b', 'c' });
但除非这是一个练习,为什么你会产生所有可能的变化?如果您提供实际要求,可能会有更好的解决方案。
答案 1 :(得分:0)
您可以使用回溯算法,代码如下。还包括输出以证明代码有效。
如果您需要将参数传递给某个帖子,请参阅this answer。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
const int MIN_LENGTH = 2;
const int MAX_LENGTH = 3;
static IList<string> vals;
static IList<string> results;
static void go(string cur)
{
if (cur.Length > MAX_LENGTH)
{
return;
}
if (cur.Length >= MIN_LENGTH && cur.Length <= MAX_LENGTH)
{
results.Add(cur);
}
foreach (string t in vals)
{
cur += t;
go(cur);
cur = cur.Substring(0, cur.Length - 1);
}
}
static int Main(string[] args)
{
vals = new List<string>();
vals.Add("a");
vals.Add("b");
vals.Add("c");
results = new List<string>();
go("");
results = results.OrderBy(x => x.Length).ToList();
foreach (string r in results)
{
Console.WriteLine(r);
}
return 0;
}
}
输出
aa
ab
ac
ba
bb
bc
ca
cb
cc
aaa
aab
aac
aba
abb
abc
aca
acb
acc
baa
bab
bac
bba
bbb
bbc
bca
bcb
bcc
caa
cab
cac
cba
cbb
cbc
cca
ccb
ccc
答案 2 :(得分:0)
public static IEnumerable<IEnumerable<T>> Permutations<T>(IEnumerable<T> source)
{
if (source == null)
throw new ArgumentNullException("source");
return permutations(source.ToArray());
}
private static IEnumerable<IEnumerable<T>> permutations<T>(IEnumerable<T> source)
{
IEnumerable<T> enumerable = source as List<T> ?? source.ToList();
var c = enumerable.Count();
if (c == 1)
yield return enumerable;
else
for (int i = 0; i < c; i++)
foreach (var p in permutations(enumerable.Take(i).Concat(enumerable.Skip(i + 1))))
yield return enumerable.Skip(i).Take(1).Concat(p);
}
private static IEnumerable<string> Subsets(char[] chars)
{
List<string> subsets = new List<string>();
for (int i = 1; i < chars.Length; i++)
{
subsets.Add(chars[i - 1].ToString(CultureInfo.InvariantCulture));
int i1 = i;
List<string> newSubsets = subsets.Select(t => t + chars[i1]).ToList();
subsets.AddRange(newSubsets);
}
subsets.Add(chars[chars.Length - 1].ToString(CultureInfo.InvariantCulture));
return subsets;
}
private static void Main()
{
char[] chars = new[]{'a','b','c'};
var subsets = Subsets(chars);
List<string> allPossibleCombPerm =
subsets.SelectMany(Permutations).Select(permut => string.Join("", permut)).ToList();
allPossibleCombPerm.ForEach(Console.WriteLine);
}
答案 3 :(得分:0)
您可以使用以下功能。 T是将组合成字符串的元素类型(将在每个项目上调用ToString())。您可以选择对表示组合的字符串使用前缀和分隔符,因此它们看起来像myprefix_A_1,myprefix_A_2等,其中_将是分隔符。
您必须使用level = 1和tmpList = null调用此函数。
public static IEnumerable<string> Combine<T>(string prefix,
string separator,
List<List<T>> collections,
int level, List<string> tmpList)
{
if (separator == null)
separator = "";
if (prefix == null)
prefix = "";
List<string> nextTmpList = new List<string>();
int length = collections.Count();
if (tmpList == null || tmpList.Count == 0)
{
tmpList = new List<string>();
foreach (var ob in collections.Last())
tmpList.Add(ob.ToString());
}
if(length == level)
{
foreach (string s in tmpList)
nextTmpList.Add(prefix + separator + s.ToString());
return nextTmpList;
}
foreach (var comb in tmpList)
foreach(var ob in collections[length - level - 1])
nextTmpList.Add(ob.ToString() + separator + comb);
return Combine(prefix, separator, collections, level + 1, nextTmpList);
}
示例:
Combine<int>("G1", "_", new List<List<int>>() { new List<int>() { 1, 3}, new List<int>() {2, 4 } }, 1, null);
输出:
G1_1_2 G1_3_2 G1_1_4 G1_3_4