How to generate password on the following standard - c#

I want to generate a password on the following standard.
One capital letter
10 Small letters
four numbers at the end
Code I have
//Gnerating a random password
string allowedChars = "";
allowedChars = "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,";
allowedChars += "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,";
allowedChars += "1,2,3,4,5,6,7,8,9,0,!,#,#,$,%,&,?";
char[] sep = { ',' };
string[] arr = allowedChars.Split(sep);
string passwordString = "";
string tempString = "";
int PasswordLength = 16;
Random rand = new Random();
for (int i = 0; i < Convert.ToInt32(PasswordLength); i++)
{
tempString = arr[rand.Next(0, arr.Length)];
passwordString += tempString;
}

There is no need to create both an upper and a lower value set. We have code for changing case. You could also extract the actual picking to a separate method, that would make it easier to test.
Here is my attempt:
void Main()
{
char[] lowerCase = new 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'};
char[] numbers = new char[] {'0','1','2','3','4','5','6','7','8','9'};
// Create the Random outside the method to avoid reseeding
Random random = new Random();
// Pick one char and make it uppercase
string password = PickRandomValueFromValueSet(1, lowerCase, random).ToUpper();
// Pick 10 lowercase chars
password+= PickRandomValueFromValueSet(10, lowerCase, random);
// Pick 4 digits
password+= PickRandomValueFromValueSet(4, numbers, random);
Console.Out.WriteLine.(password);
}
string PickRandomValueFromValueSet(int number, char[] valueSet, Random random)
{
string result = "";
for (int i = 0; i < number; i++)
{
result += valueSet[random.Next(0, valueSet.Length)];
}
return result;
}
I don't see why !,#,#,$,%,& and ? were allowed as numbers in the question. I have omitted those.

You need to add different chars to your password string in this way:
string lowerChars = "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,";
string[] lowerCharsArr = lowerChars.Split(sep);
string upperChars = "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,";
string[] upperCharsArr = upperChars.Split(sep);
string numbers = "1,2,3,4,5,6,7,8,9,0";
string[] numbersArr = numbers.Split(sep);
string others = "!,#,#,$,%,&,?";
string[] othersArr = others.Split(sep);
string passwordString = "";
int PasswordLength = 16;
Random rand = new Random();
passwordString += upperChars[rand.Next(0, upperChars.Length)];
for (int i = 1; i < Convert.ToInt32(PasswordLength -4); i++)
{
passwordString += lowerChars[rand.Next(0, lowerChars.Length)];
}
for (int i = 0; i < 4; i++)
{
passwordString += numbersArr[rand.Next(0, numbersArr.Length)];
}

Here's one way you could do this, optionally shuffling the result with the extension method .Shuffle, but if you really want to keep the order of upper first, then lower, then 4 digit/symbols at the end just leave that out.
namespace PasswordGen
{
public class Program
{
private static Random _random = new Random();
static void Main(string[] args)
{
var nonAlphaSymbols = "1234567890!##$%&?";
var password = new[] { (char)_random.Next('A', 'Z' + 1) } // upper case character
.Concat(Enumerable.Range(0, 10).Select(a => (char)_random.Next('a', 'z' + 1)) // 10 lower case
.Concat(Enumerable.Range(0, 4).Select(a => nonAlphaSymbols[_random.Next(0, nonAlphaSymbols.Length)]))) // 4 from nonAlpha
.Shuffle(); // optional, if you want to shuffle the outcome
Console.WriteLine(new string(password.ToArray()));
}
}
public static class Extensions
{
private static Random _random = new Random();
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> input)
{
List<T> output = new List<T>(input);
for (int i = 0; i < output.Count; i++)
{
var swapTarget = _random.Next(i, output.Count - 1);
T temp = output[swapTarget];
output[swapTarget] = output[i];
output[i] = temp;
}
return output;
}
}
}
Example: https://dotnetfiddle.net/BLOEgy

Related

I'm generating a list of 100 random "names", now I need to follow it up with 100 more names and 100 random numbers. C#

I'm making a program that generates the "names" (random lines of text from the ASCII) that are the names of movies in this instance. I should follow them up with a "name" of a director for each (can also be generated from the ASCII), and after that the random year that is the year the "movie" was made (from 1896 to 2021).
I have two separate functions that randomize the names of the movies and directors, but I'm confused with the supposed placement of the Console.Writeline which the intelligence only allows inside their own loops. Otherwise it doesn't seem to be able to use the values "directorname" and "moviename".
I need it to write the names in a single line, ai. (KHGTJ, KGHTJF).
Also I need a way to generate a random year from 1896 to 2021 that is printed after the names of the movie, and director, ai. (KFJU, MDDOS, 1922).
private static void GenerateRandomNames()
{
Random random = new Random();
char y = (char)65;
for (int p = 0; p < 100; p++)
{
string directorname = "";
for (int m = 0; m < 5; m++)
{
int b = random.Next(65, 90);
y = (char)b;
directorname += y;
}
Console.WriteLine(directorname);
}
Random rnd = new Random();
char x = (char)65;
for (int j = 0; j < 100; j++)
{
string moviename = "";
for (int i = 0; i < 5; i++)
{
int a = rnd.Next(65, 90);
x = (char)a;
moviename += x;
}
Console.WriteLine(moviename);
}
Console.WriteLine();
I need to fix the plecement of the Console.Writeline() so it can print both names in the same line, and be able to print the year after them.
I've tried placing the Console.Writeline() outside the loops, but of course it can't then use the name. But this way it prints them the wrong way.
If you want to have minimal changes in your code, you can use the following code:
private static void GenerateRandomNames()
{
//a separate thing for the names of the directors (ASCII)
// then for the years they were made (1896-2021)
//they should all be printed in the end ie. (KGMFK, JDBDJ, 1922)
Random rnd = new Random();
char x = (char)65;
for (int j = 0; j < 100; j++)
{
string directors = "";
string moviename = "";
for (int i = 0; i < 5; i++)
{
int a = rnd.Next(65, 90);
x = (char)a;
moviename += x;
}
for (int i = 0; i < 5; i++)
{
int a = rnd.Next(65, 90);
x = (char)a;
directors += x;
}
Console.WriteLine("( "+directors +", "+ moviename + ", " +rnd.Next(1896, 2021).ToString()+" )");
}
Console.WriteLine();
}
and result:
Not sure if it is good to answer this type of question, but answering it anyway.
Since you only want other 5-letter words and 4-digit numbers ranging from 1896 - 2021,
Just get another variable 'b' and do the same as you did for 'a', like :
int b = rnd.Next(65,90) ;
y = char(b) ;
director name += y ;
and to get the year value, you can use this :
year = rnd.Next(1896,2021)
So, by combining all of the above, you have the code like this :
internal class Program
{
private static void GenerateRandomNames()
{
Random rnd = new Random();
char x = (char)65;
char y = (char) 65 ;
for (int j = 0; j < 100; j++)
{
string moviename = "";
string directorName = "";
int year = rnd.Next(1896,2021);
for (int i = 0; i < 5; i++)
{
int a = rnd.Next(65, 90);
int b = rnd.Next(65, 90);
x = (char)a;
moviename += x;
y = (char)a;
directorName += x;
}
Console.WriteLine(moviename);
Console.WriteLine(directorName);
Console.WriteLine(year);
}
Console.WriteLine();
}
static void Main(string[] args)
{
GenerateRandomNames();
}
}
The task becomes easier if you extract the creation of a random name to a new method. This allows you to call it twice easily. I moved the random object to the class (making it a class field), so that it can be reused in different places.
internal class Program
{
private static readonly Random _rnd = new Random();
private static string CreateRandomName(int minLength, int maxLength)
{
string name = "";
for (int i = 0; i < _rnd.Next(minLength, maxLength + 1); i++)
{
char c = (char)_rnd.Next((int)'A', (int)'Z' + 1);
name += c;
}
return name;
}
private static void WriteRandomNames()
{
for (int i = 0; i < 100; i++)
{
string movie = CreateRandomName(4, 40);
string director = CreateRandomName(3, 30);
int year = _rnd.Next(1896, 2022);
Console.WriteLine($"{movie}, {director}, {year}");
}
Console.WriteLine();
}
static void Main(string[] args)
{
WriteRandomNames();
}
}
Note that the second parameter of the Next(Int32, Int32) method is the exclusive upper bound. Therefore I added 1.
output:
HATRHKYAHQTGS, NCPQ, 1999
QVJAYOTTISN, LJTGJDMB, 2018
JEXJDICLRMZFRV, GJPZHFBHOTR, 1932
SKFINIGVYUIIVBD, DIZSKOS, 1958
LWWGSEIZT, AMDW, 1950
OAVZVQVFPPBY, SPEZZE, 2008
YLNTZZIXOCNENGYUL, URNJMK, 1962
ONIN, WUITIL, 1987
RJUXGORWDVQRILDWWKSDWF, MOEYPZQPV, 1946
YUQSSOPZTCTRM, UEPPXIVGERG, 1994
KILWEYC, QJZOTLKFMVPHUE, 1915
Wow, in the time it took me to write an answer, three or more others appeared. They all seem like pretty good answers to me, but since I went to the trouble of writing this code, here you go. :)
I focused on using the same Random in different ways, because I think that's what you were asking about.
using System;
using System.Collections.Generic;
using System.Linq;
Random rnd = new Random(1950);
GenerateRandomNames();
void GenerateRandomNames()
{
for (int j = 0; j < 100; j++)
{
// here's one way to get a random string
string name = Guid.NewGuid().ToString().Substring(0, 5);
string description = new string(GetRandomCharacters(rnd.Next(5,16)).ToArray());
string cleaner = new string(GetCleanerCharacters(rnd.Next(5, 16)).ToArray());
string preferred = new string(GetPreferredRandomCharacters(rnd.Next(5, 16)).ToArray());
int year = rnd.Next(1896, DateTime.Now.Year + 1);
Console.WriteLine($"{year}\t{preferred}");
Console.WriteLine($"{year}\t{cleaner}");
Console.WriteLine($"{year}\t{name}\t{description}");
Console.WriteLine();
}
Console.WriteLine();
}
// Not readable
IEnumerable<char> GetRandomCharacters(int length = 5)
{
for (int i = 0; i < length; i++)
{
yield return Convert.ToChar(rnd.Next(0, 255));
}
}
// gives you lots of spaces
IEnumerable<char> GetCleanerCharacters(int length = 5)
{
for (int i = 0; i < length; i++)
{
char c = Convert.ToChar(rnd.Next(0, 255));
if (char.IsLetter(c))
{
yield return c;
}
else
{
yield return ' ';
}
}
}
// Most readable (in my opinion), but still nonsense.
IEnumerable<char> GetPreferredRandomCharacters(int length = 5)
{
for (int i = 0; i < length; i++)
{
bool randomSpace = rnd.Next(0, 6) == 3;
if (i > 0 && randomSpace) // prevent it from starting with a space
{
yield return ' ';
continue;
}
var c = Convert.ToChar(rnd.Next(65, 91)); // uppercase letters
if (rnd.Next(0, 2) == 1)
{
c = char.ToLower(c);
}
yield return c;
}
}

How to generate random alphanumeric string from a given string in C#?

I have a string. I want to generate a random string from this string, by replacing a number by a random number. lower character by lower character and upper character by upper character. And remaining characters as it is.
I have written the below code. I need to call this method millions of time on different strings (string length is not more than 100 characters), It's taking too much time.
private static string GenerateRandomAlphanumericValue(string input) {
char[] newStr = new char[input.Length];
char[] alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
char[] alphaL = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
char[] number = "0123456789".ToCharArray();
Random random = new Random();
for (int i = 0; i < input.Length; i++) {
if (char.IsNumber(input[i])) {
int index = random.Next(0, number.Length);
newStr[i] = number[index];
}
else if (char.IsUpper(input[i])) {
int index = random.Next(0, alphaU.Length);
newStr[i] = alphaU[index];
}
else if (char.IsLower(input[i])) {
int index = random.Next(0, alphaL.Length);
newStr[i] = alphaL[index];
}
else {
newStr[i] = input[i];
}
}
return string.Join("", newStr);
}
I need help in optimizing the code or there any be a different approach to solve the problem.
Input: vivEK123$% ~a
Output: ajrLW854$% ~w
Try this
static char[] alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
static char[] alphaL = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
static char[] number = "0123456789".ToCharArray();
static Random random = new Random();
static StringBuilder sb = new StringBuilder(100);
private static string GenerateRandomAlphanumericValue(string input)
{
sb.Clear();
for (int i = 0; i < input.Length; i++)
{
if (char.IsNumber(input[i]))
{
int index = random.Next(0, number.Length);
sb.Append(number[index]);
}
else if (char.IsUpper(input[i]))
{
int index = random.Next(0, alphaU.Length);
sb.Append(alphaU[index]);
}
else if (char.IsLower(input[i]))
{
int index = random.Next(0, alphaL.Length);
sb.Append(alphaL[index]);
}
else
{
sb.Append(input[i]);
}
}
return sb.ToString();
}
Instead of using arrays, you could just randomize based on the ASCII-value range of characters. I'd also suggest using StringBuilder to build the result string.
public class Randomizer{
private static Random rng = new Random();
public static string RandomizeString(string input){
StringBuilder sb = new StringBuilder();
foreach(char c in input){
if(Char.IsNumber(c)){
sb.Append(rng.Next(0,10));
}
else if(Char.IsLower(c)){
sb.Append((char)rng.Next(97,123));
}
else if(Char.IsUpper(c)){
sb.Append((char)rng.Next(65,91));
}
else{
sb.Append(c);
}
}
return sb.ToString();
}
}
Note: a-z is ASCII 97-122, A-Z is ASCII 65-90, and 0-9 is just an integer cast to a string.
This is a little more efficient. I'm not sure about execution time :
private static string GenerateRandomAlphanumericValue(string input)
{
string newStr = "";
string alphaU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string alphaL = "abcdefghijklmnopqrstuvwxyz";
string number = "0123456789";
Random random = new Random();
for (int i = 0; i < input.Length; i++)
{
if (char.IsNumber(input[i]))
{
int index = random.Next(0, number.Length);
newStr += number[index];
}
else if (char.IsUpper(input[i]))
{
int index = random.Next(0, alphaU.Length);
newStr += alphaU[index];
}
else if (char.IsLower(input[i]))
{
int index = random.Next(0, alphaL.Length);
newStr += alphaL[index];
}
else
{
newStr += input[i];
}
}
return newStr;
}
The general principle is to move as much as possible out of loops and to use the least expensive techniques inside loops.
Random only needs to be constructed once.
StringBuilder is one of the more efficient ways of moving individually acquire Chars into a String. And, it needs to be constructed only once (but introduces thread safety issues).
Array indexing is one fast way to replace chain logic but might not be the fastest since there are only three ranges. (if >= && <= times three could be faster.)
IsUpper et al might have a big impact on its performance. They have to account for all Unicode codepoints in the general category Lu, Ll or Nd.
private static readonly Random random = new Random();
private static readonly StringBuilder sb = new StringBuilder(100);
// min and max are the replacement range for indexing Char.
private static readonly Char[] min = new Char[Char.MaxValue + 1];
private static readonly Char[] max = new Char[Char.MaxValue + 1];
static UserQuery()
{
foreach (var range in new[] {
(min: 'A', max: 'Z'),
(min: 'a', max: 'z'),
(min: '0', max: '9') })
{
for (var c = range.min; c <= range.max; c++)
{
min[c] = range.min;
max[c] = range.max;
}
}
}
private static String GenerateRandomAlphanumericValue(String input)
{
sb.Clear();
foreach (var c in input)
{
sb.Append((Char)random.Next(min[c], max[c]));
}
return sb.ToString();
}

Random String Generator that does not repeat

I've been using this random string generator. But my problem is that this random string generator is repeating itself. I've heard of using the shuffle method but I dont know how to implement it in my code. Any help will be mostly appreciated.
private static Random random = new Random();
public static string RandomString(int length)
{
const string chars = "0123456789";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
public static string RandomString2(int length)
{
const string chars = "AB";
return new string(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
And then in the page load i actually call my 2 methods and combine them in a textbox.
string dummy = RandomString(1);
string dummy2 = RandomString2(1);
txtTagNumber.Text = dummy2.ToString() + dummy.ToString();
This might do the trick for you.
Random random = new Random();
const string numchars = "0123456789";
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
List<string> randStr = new List<string>();
for(int i = 0; i <= 10; i++)
{
string AlphaRandom = new string(Enumerable.Repeat(chars, 1)
.Select(s => s[random.Next(s.Length)]).ToArray());
string NumberRandom = new string(Enumerable.Repeat(numchars, 1)
.Select(s => s[random.Next(s.Length)]).ToArray());
if(randStr.Contains(AlphaRandom + NumberRandom))
{
i--;
}
else
{
randStr.Add(AlphaRandom + NumberRandom);
Console.WriteLine(randStr[i]);
}
}
Created a random of Random Type then took 2 strings one for alphabets and another for numbers. Created a list of string to add all generated random strings to it. In the loop I am trying to generate 10 random strings. Checking if the list of Random String contains the string which has been generated earlier. if yes then decrement the value of i so that it would still generate 10 strings. and if no matches found than Random string will be added to the list.
Hope this helps
Another way would be to create a list of all the choices. Then whenever the user makes a choice remove it from the list. Choose random indexes from that list to yield only unique choices:
List<string> choices = new List<string>();
Random rnd = new Random(DateTime.Now.Millisecond);
public void PopulateChoices()
{
choices.Clear();
for(char i = '0'; i < ':';i++)
{
for(char j = 'A'; j < 'C'; j++)
{
choices.Add(new string(new char[] { j, i }));
}
}
}
public List<string> MakeRandColl(int size)
{
List<string> randChoices = choices;
List<string> retVal = new List<string>();
for(int i = 0; i < size; i++)
{
string temp = randChoices[rnd.Next(0, randChoices.Count)];
retVal.Add(temp);
randChoices.Remove(temp);
}
return retVal;
}
public void DeleteChoice(string choice)
{
choices.Remove(choice);
}

Array to new string

I'm making a webshop for school and had a quick question.
I'm trying to write a code that generates a random coupon code and it actually works (did some extreme programming in Console Application), but it's simply not efficient.
static void Main(string[] args)
{
Random r = new Random();
string ALphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int size = 4;
char[] code1 = new char[size]
char[] code2 = new char[size]
char[] code3 = new char[size]
for (int i = 0; i < size; i++)
{
code1[i] = Alphabet[r.Next(Alphabet.Length)];
code2[i] = Alphabet[r.Next(Alphabet.Length)];
code3[i] = Alphabet[r.Next(Alphabet.Length)];
}
string code4 = new string(code1);
string code5 = new string(code2);
string code6 = new string(code3);
Console.WriteLine(code4 + " - " + code5 + " - " + code6);
Console.ReadLine();
}
This works.. somehow. But I would like to see it more efficient, because when I want to generate 100 coupons... this isn't really the way to do that.
I did see something on joining strings, use string.Insert to get that " - " in between and loop it multiple times, but I couldn't get a clear tutorial on how to do that with... well this kind of code.
Anyone got a efficient and (preferable) easy solution?
=======
UPDATE!
this does end up in a database eventually
You could be using a StringBuilder for this:
StringBuilder sb = new StringBuilder();
Random r = new Random();
string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int size = 16;
for (var i = 0; i < size; i++)
{
sb.Append(Alphabet[r.Next(Alphabet.Length)]);
}
Console.WriteLine(sb.ToString());
If you want less code you can make use of a GUID and format it.
Guid.NewGuid().ToString("N").Substring(0, 16);
Update, just saw you needed some formatting between each part of the coupon, so I changed it a litle bit:
StringBuilder sb = new StringBuilder();
Random r = new Random();
string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int pieces = 3, pieceSize = 4;
for (var i = 0; i < pieces; i++)
{
if(i != 0)
sb.Append(" - ");
for (var j = 0; j < pieceSize; j++)
{
sb.Append(Alphabet[r.Next(Alphabet.Length)]);
}
}
Console.WriteLine(sb.ToString());
Code is not quite good, but for school app will play I guess )
static string GenerateCoupon(Random r)
{
string Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int size = 4;
char[] code1 = new char[size];
char[] code2 = new char[size];
char[] code3 = new char[size];
for (int i = 0; i < size; i++)
{
code1[i] = Alphabet[r.Next(Alphabet.Length)];
code2[i] = Alphabet[r.Next(Alphabet.Length)];
code3[i] = Alphabet[r.Next(Alphabet.Length)];
}
string code4 = new string(code1);
string code5 = new string(code2);
string code6 = new string(code3);
return string.Format("{0}-{1}-{2}", code4, code5, code6);
}
static void Main(string[] args)
{
Random rnd = new Random();
for (int i = 0; i < 100;i++ )
Console.WriteLine(GenerateCoupon(rnd));
Console.ReadLine();
}

Function that generates strings according to input

I need a C# function that takes 2 strings as an input and return an array of all possible combinations of strings.
private string[] FunctionName(string string1, string string2)
{
//code
}
The strings input will be in the following format:
string1: basement
string2: a*fa
Now what I need is all combinations of possible strings using the characters in String2 (ignoring the * symbols), and keeping them in the same character position like this:
baaement, baaefent, baaefena, basefent, basemena, etc.
EDIT:
This is not homework. I need this function for a piece of a program I am doing.
The following is the code I have so far but it has some 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();
}//
It does sound like homework. As a suggestion, I would ignore the first parameter and focus on getting all possible permutations of the second string. What's turned off, what's turned on, etc. From that list, you can easily come up with a method of swapping out characters of the first string.
On that note, I'm in the uncomfortable position of having a function ready to go but not wanting to post it because of the homework implication. I'd sure love for somebody to review it, though! And technically, there's two functions involved because I just happened to already have a generic function to generate subsets lying around.
Edit: OP says it isn't homework, so here is what I came up with. It has been refactored a bit since the claim of two functions, and I'm more than open to criticism.
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;
}
}
}
since it's hopw work I'd only suggest some way to solve the problem rather than writing the code.
if you loop the second parameter every time you hit a letter you'll have to options either use the letter from the first argument or the letter from the second. collect all these optins together with the index. keep a list of the parts from the first argument that will never change. iterate thorugh those two lists to created all the possible permutations
Decimal to Binary converted code is stolon copied from here.
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;
}
which password cracker do you want to program? :)
how about
if string2 contains '*'
foreach(char ch in string1)
replace first * with ch,
execute FunctionName
else
print string2

Categories

Resources