Função que gera strings de acordo com a entrada
-
21-09-2019 - |
Pergunta
Preciso de uma função C# que pegue 2 cordas como uma entrada e retorne uma matriz de todas as combinações possíveis de strings.
private string[] FunctionName(string string1, string string2)
{
//code
}
A entrada de strings estará no seguinte formato:
string1
: porão
string2
: a*fuma
Agora, o que eu preciso são todas as combinações de seqüências possíveis usando os caracteres em String2 (ignorando os símbolos *) e mantê -los na mesma posição de personagem como esta:
baaement, baaefent, baaefena, basefent, basemena, etc.
EDIT: Isso não é dever de casa. Eu preciso dessa função para um pedaço de um programa que estou fazendo. A seguir, o código que tenho até agora, mas tem alguns bugs.
static List<string> combinations = new List<string>();
static void Main(string[] args)
{
//include trimming of input string
string FoundRes = "incoming";
string AltRes = "*2*45*78";
List<int> loc = new List<int>();
string word = "";
for (int i = 0; i < AltRes.Length; i++)
{
if (AltRes[i] != '*')
{
loc.Add(i);
word += AltRes[i];
}
}
generate(word);
string[] aaa = InsertSymbol(FoundRes, loc.ToArray(), AltRes, combinations);
Console.WriteLine("input string: " + FoundRes);
Console.WriteLine("Substitute string: " + AltRes);
Console.WriteLine("============Output============");
for (int j = 0; j < aaa.Length; j++)
{
Console.WriteLine(aaa[j]);
}
Console.ReadKey();
}//
private static void generate(string word)
{
// Add this word to combination results set
if (!combinations.Contains(word))
combinations.Add(word);
// If the word has only one character, break the recursion
if (word.Length == 1)
{
if (!combinations.Contains(word))
combinations.Add(word);
return;
}
// Go through every position of the word
for (int i = 0; i < word.Length; i++)
{
// Remove the character at the current position
// call this method with the String
generate(word.Substring(0, i) + word.Substring(i + 1));
}
}//
private static string[] InsertSymbol(string orig, int[] loc, string alternative, List<string> Chars)
{
List<string> CombinationsList = new List<string>();
string temp = "";
for (int i = 0; i < Chars.Count; i++)
{
temp = orig;
for (int j = 0; j < Chars[i].Length; j++)
{
string token = Chars[i];
if (alternative.IndexOf(token[j]) == loc[j])
{
temp = temp.Remove(loc[j], 1);
temp = temp.Insert(loc[j], token[j].ToString());
// int pos = sourceSubst.IndexOf(token[j]);
// sourceSubst = sourceSubst.Remove(pos, 1);
// sourceSubst = sourceSubst.Insert(pos, ".");
}
else
{
temp = temp.Remove(alternative.IndexOf(token[j]), 1);
temp = temp.Insert(alternative.IndexOf(token[j]), token[j].ToString());
}
}
CombinationsList.Add(temp);
}
return CombinationsList.ToArray();
}//
Solução
Parece lição de casa. Como sugestão, eu ignorava o primeiro parâmetro e focava em obter todas as permutações possíveis da segunda sequência. O que está desligado, o que está ativado, etc. dessa lista, você pode facilmente criar um método de trocar os personagens da primeira string.
Nessa nota, estou na posição desconfortável de ter uma função pronta para ir, mas não querendo publicá -la por causa da implicação da lição de casa. Eu certamente adoraria alguém para revisá -lo! E tecnicamente, há duas funções envolvidas porque eu já tinha uma função genérica para gerar subconjuntos por aí.
EDIT: OP diz que não é o dever de casa, então aqui está o que eu criei. Foi refaturado um pouco desde a reivindicação de duas funções, e eu sou mais do que aberto a críticas.
using System;
using System.Collections.Generic;
using System.Text;
class Program
{
static void Main()
{
string original = "phenomenal";
string pattern = "*xo**q*t**";
string[] replacements = StringUtility.GetReplacementStrings(original, pattern, true);
foreach (string replacement in replacements)
Console.WriteLine(replacement);
Console.Read();
}
public static class StringUtility
{
public static string[] GetReplacementStrings(string original, string pattern, bool includeOriginal)
{
// pattern and original might not be same length
int maxIndex = Math.Max(original.Length, pattern.Length);
List<int> positions = GetPatternPositions(pattern, maxIndex, '*');
List<int[]> subsets = ArrayUtility.CreateSubsets(positions.ToArray());
List<string> replacements = GenerateReplacements(original, pattern, subsets);
if (includeOriginal)
replacements.Insert(0, original);
return replacements.ToArray();
}
private static List<string> GenerateReplacements(string original, string pattern, List<int[]> subsets)
{
List<string> replacements = new List<string>();
char[] temp = new char[original.Length];
foreach (int[] subset in subsets)
{
original.CopyTo(0, temp, 0, original.Length);
foreach (int index in subset)
{
temp[index] = pattern[index];
}
replacements.Add(new string(temp));
}
return replacements;
}
private static List<int> GetPatternPositions(string pattern, int maxIndex, char excludeCharacter)
{
List<int> positions = new List<int>();
for (int i = 0; i < maxIndex; i++)
{
if (pattern[i] != excludeCharacter)
positions.Add(i);
}
return positions;
}
}
public static class ArrayUtility
{
public static List<T[]> CreateSubsets<T>(T[] originalArray)
{
List<T[]> subsets = new List<T[]>();
for (int i = 0; i < originalArray.Length; i++)
{
int subsetCount = subsets.Count;
subsets.Add(new T[] { originalArray[i] });
for (int j = 0; j < subsetCount; j++)
{
T[] newSubset = new T[subsets[j].Length + 1];
subsets[j].CopyTo(newSubset, 0);
newSubset[newSubset.Length - 1] = originalArray[i];
subsets.Add(newSubset);
}
}
return subsets;
}
}
}
Outras dicas
Como é o trabalho Hopw, eu sugeriria apenas uma maneira de resolver o problema em vez de escrever o código.
Se você lotar o segundo parâmetro toda vez que chegar a uma carta que terá para opções, use a letra do primeiro argumento ou a carta do segundo. Colete todas essas opções junto com o índice. Mantenha uma lista das peças do primeiro argumento que nunca mudará. itera Thorugh essas duas listas para criar todas as permutações possíveis
Código convertido decimal a binário é Stolon copiado de aqui.
static void Main()
{
string string1 = "basement";
string string2 = "**a*f**a";
string[] result = GetCombinations(string1, string2);
foreach (var item in result)
{
Console.WriteLine(item);
}
}
private static string[] GetCombinations(string string1, string string2)
{
var list = new List<List<char>> { new List<char>(), new List<char>() };
var cl = new List<char>();
List<string> result = new List<string>();
for (int i = 0; i < string1.Length; i++)
{
if (string2[i] == '*')
{
cl.Add(string1[i]);
}
else
{
list[0].Add(string1[i]);
list[1].Add(string2[i]);
}
}
int l = list[0].Count;
for (int i = 0; i < (Int64)Math.Pow(2.0,l); i++)
{
string s = ToBinary(i, l);
string ss = "";
int x = 0;
int y = 0;
for (int I = 0; I < string1.Length; I++)
{
if (string2[I] == '*')
{
ss += cl[x].ToString();
x++;
}
else
{
ss += (list[int.Parse(s[y].ToString())][y]);
y++;
}
}
result.Add(ss);
}
return result.ToArray<string>();
}
public static string ToBinary(Int64 Decimal, int width)
{
Int64 BinaryHolder;
char[] BinaryArray;
string BinaryResult = "";
while (Decimal > 0)
{
BinaryHolder = Decimal % 2;
BinaryResult += BinaryHolder;
Decimal = Decimal / 2;
}
BinaryArray = BinaryResult.ToCharArray();
Array.Reverse(BinaryArray);
BinaryResult = new string(BinaryArray);
var d = width - BinaryResult.Length;
if (d != 0) for (int i = 0; i < d; i++) BinaryResult = "0" + BinaryResult;
return BinaryResult;
}
Qual cracker de senha você deseja programar? :) e quanto a
if string2 contains '*'
foreach(char ch in string1)
replace first * with ch,
execute FunctionName
else
print string2