C# Remove An Empty Character Array - c#

I have character arrays seperated into multiple groups, my code uses a character from every group, so once character in a group is processed it will go to the next. I want to remove a group when it's considered empty. (or alternative if you can help fix the code so it skips empty groups)
In the form, there are checkboxes which add the specific characters to their specified group, you have the option to add those characters of choice or not, which I also have a user include input textbox if they want to add their personal characters, but in a case of a char group being empty I get an exception most likely due to the group having no characters.
Exception:
"System.IndexOutOfRangeException: 'Index was outside the bounds of the
array."
For
"result[i] = charGroups[nextGroupIdx][nextCharIdx];"
char[][] charGroups = new char[][]
{
CapitalCharacterSet.ToCharArray(),
LowercaseCharacterSet.ToCharArray(),
NumbersCharacterSet.ToCharArray(),
IncludeCharacterSet.ToCharArray(),
SpecialCharacterSet.ToCharArray()
};
FULL CODE:
char[][] charGroups = new char[][]
{
CapitalCharacterSet.ToCharArray(),
LowercaseCharacterSet.ToCharArray(),
NumbersCharacterSet.ToCharArray(),
IncludeCharacterSet.ToCharArray(),
SpecialCharacterSet.ToCharArray()
};
int[] charsLeftInGroup = new int[charGroups.Length];
for (int i = 0; i < charsLeftInGroup.Length; i++)
charsLeftInGroup[i] = charGroups[i].Length;
int[] leftGroupsOrder = new int[charGroups.Length];
for (int i = 0; i < leftGroupsOrder.Length; i++)
leftGroupsOrder[i] = i;
byte[] randomBytes = new byte[4];
RNGCryptoServiceProvider rng = new();
rng.GetBytes(randomBytes);
int seed = BitConverter.ToInt32(randomBytes, 0);
Random random = new(seed);
char[] result = null;
result = new char[length.Value];
int nextCharIdx;
int nextGroupIdx;
int nextLeftGroupsOrderIdx;
int lastCharIdx;
int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
for (int i = 0; i < result.Length; i++)
{
if (lastLeftGroupsOrderIdx == 0)
nextLeftGroupsOrderIdx = 0;
else
nextLeftGroupsOrderIdx = random.Next(0, lastLeftGroupsOrderIdx);
nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
if (lastCharIdx == 0)
nextCharIdx = 0;
else
nextCharIdx = random.Next(0, lastCharIdx + 1);
try
{
result[i] = charGroups[nextGroupIdx][nextCharIdx];
}
catch
{
if (lastCharIdx == 0)
nextCharIdx = 0;
else
nextCharIdx = random.Next(0, lastCharIdx + 1);
}
if (lastCharIdx == 0)
charsLeftInGroup[nextGroupIdx] = charGroups[nextGroupIdx].Length;
else
{
if (lastCharIdx != nextCharIdx)
{
char temp = charGroups[nextGroupIdx][lastCharIdx];
charGroups[nextGroupIdx][lastCharIdx] =
charGroups[nextGroupIdx][nextCharIdx];
charGroups[nextGroupIdx][nextCharIdx] = temp;
}
charsLeftInGroup[nextGroupIdx]--;
}
if (lastLeftGroupsOrderIdx == 0)
lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
else
if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
{
int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
leftGroupsOrder[lastLeftGroupsOrderIdx] =
leftGroupsOrder[nextLeftGroupsOrderIdx];
leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
}
lastLeftGroupsOrderIdx--;
}
}

Related

Cross Search generate char Matrix

I am trying to create a word search puzzle matrix, this is the code I have,
static void PlaceWords(List<string> words)
{
Random rn = new Random();
foreach (string p in words)
{
String s = p.Trim();
bool placed = false;
while (placed == false)
{
int nRow = rn.Next(0,10);
int nCol = rn.Next(0,10);
int nDirX = 0;
int nDirY = 0;
while (nDirX == 0 && nDirY == 0)
{
nDirX = rn.Next(3) - 1;
nDirY = rn.Next(3) - 1;
}
placed = PlaceWord(s.ToUpper(), nRow, nCol, nDirX, nDirY);
}
}
}
static bool PlaceWord(string s, int nRow, int nCol, int nDirX, int nDirY)
{
bool placed = false;
int LetterNb = s.Length;
int I = nRow;
int J = nCol;
if (MatriceIndice[nRow, nCol] == 0)
{
placed = true;
for (int i = 0; i < s.Length-1; i++)
{
I += nDirX;
J += nDirY;
if (I < 10 && I>0 && J < 10 && J>0)
{
if (MatriceIndice[I, J] == 0)
placed = placed && true;
else
placed = placed && false;
}
else
{
return false;
}
}
}
else
{
return false;
}
if(placed==true)
{
int placeI = nRow;
int placeJ = nCol;
for (int i = 0; i < s.Length - 1; i++)
{
placeI += nDirX;
placeJ += nDirY;
MatriceIndice[placeI,placeJ] = 1;
MatriceChars[placeJ, placeJ] = s[i];
}
}
return placed;
}
However it seems like it is an infinite loop. I am trying to add the code in a 1010 char matrix linked to a 1010 int matrix initially filled with 0 where I change the cases to 1 if the word is added to the matrix. How should I fix the code?
There are several errors. First,
MatriceChars[placeJ, placeJ] = s[i];
should be
MatriceChars[placeI, placeJ] = s[i];
Second,
for (int i = 0; i < s.Length - 1; i++)
(two occurrences) should be
for (int i = 0; i < s.Length; i++)
(You do want all the letters in the words, right?)
Third, when testing indices, you should use I >= 0, not I > 0, as the matrix indices start at 0.
However, the main logic of the code seems to work, but if you try to place too many words, you will indeed enter an infinite loop, since it just keeps trying and failing to place words that can never fit.

I am unable to use substring. How can I fix this?

I am trying to see weather the string is in alphabetical order or no and this error pops up
System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
Parameter name: length
at System.String.Substring(Int32 startIndex, Int32 length)
at Rextester.Program.Main(String[] args)**
public static void Main(string[] args)
{
string str = "bat\ncat\ndog\n";
int c = 0;
for (int i = 0; i < str.Length; i++)
{
if ((str.Substring(i,i + 1).Equals("\n")))
{
c++;
}
}
String[] strArray = new String[c + 1]; //declare with size
int g = 0;
String h = "";
for (int i = 0; i < str.Length; i++)
{
if ((str.Substring(i,i + 1).Equals("\n")))
{
strArray[g] = h;
h = "";
g = g + 1;
}
else
{
h = h + str.Substring(i,i + 1);
}
}
String p = "True";
for (int i = 0; i < g; i++)
{
if (i < (g - 1))
{
String f = strArray[i];
String g2 = strArray[i + 1];
char d = f[0];
char s = g2[0];
int d1 = (int)d;
int s1 = (int)s;
if (d1 > s1)
{
p = "False";
}
}
}
Console.WriteLine(p);
}
}
Not sure about what you are doing in your second loop and why is it so complex. We can do the same like this. Hope this helps.
using System;
public class Program
{
public static void Main()
{
string str = "abcd";
str = str.Replace('\n',' ');
String p = "True";
for (int i = 1; i < str.Length; i++) {
// if element at index 'i' is less
// than the element at index 'i-1'
// then the string is not sorted
if (str[i] < str[i - 1]) {
p = "false";
}
}
Console.WriteLine(p);
}
}
Pay attention to the definition of substring
The substring starts at a specified character position and has a
specified length
Considering your first use of substring, here
for (int i = 0; i < str.Length; i++)
{
if (str.Substring(i, i + 1).Equals("\n"))
{
c++;
}
}
What happens when we get to i=6 here? Substring tries to give you a new string that starts at position i = 6, and is length = 7 characters long. So it tries to give you 7 characters starting from str[6] to str[12]. Well, there is no str[12], so you get an exception.
Its clear that your intent is NOT to get a string that starts at position 6 and is 7 characters long. You want ONE character, so your loop should be this
for (int i = 0; i < str.Length; i++)
{
if (str.Substring(i, 1).Equals("\n"))
{
c++;
}
}
But theres a much simpler way to get your words in alphabetical order using LINQ
string str = "bat\ncat\ndog\n";
//Removes the trailing \n so you don't have one entry that is only whitespace
str = str.Trim();
string[] strSplit = str.Split('\n').OrderBy(x => x[0]).ToArray();
Now all substrings are sorted alphabetically and you can do whatever you want with them

I need to write a program that generates all possible combinations of the word password in upper and lowercase

I need to generate all upper and lower case permutations of the word 'password',however sometimes I swop out the chars a for #, s for 5 and o for 0,so I need to come up with all combinations so that my dictionary can eventually crack the password.This is a homework question btw.
I have already gotten a permutation to work on upper and lowercase but im unsure as to how to proceed to the steps where I substitute letters for symbols/numbers.
public List<string> permute(String input)
{
var list = new List<string>();
int n = input.Length;
// Number of permutations is 2^n
int max = 1 << n;
// Converting string
// to lower case
input = input.ToLower();
// Using all subsequences
// and permuting them
for (int i = 0; i < max; i++)
{
char[] combination = input.ToCharArray();
// If j-th bit is set, we
// convert it to upper case
for (int j = 0; j < n; j++)
{
if (((i >> j) & 1) == 1)
combination[j] = (char)(combination[j] - 32);
}
string tmp = new string(combination);
bool add = false;
//if combination contains 32(space) ,16(0),21(5) and dont add
foreach (char c in combination)
{
if (((c) == 32) || (c) == 16 || (c) == 21) //add 0 and 5
{
//dont add
add = false;
//break on first instance
break;
}
else
{
add = true;
}
}
// Printing current combination
Console.Write(combination);
Console.Write(" ");
if (add) list.Add(tmp);
}
return list;
}
static void Main(string[] args)
{
var pass1 = new List<string>();
var pass2 = new List<string>();
var pass3 = new List<string>();
var pass4 = new List<string>();
var pass5 = new List<string>();
Permute p = new Permute();
pass1 = p.permute("password");//this works well
//Replae a with #
pass2 = p.permute("p#ssword"); //remove all values with no a
//REplace o with 0
pass3 = p.permute("passw0rd"); //remove all values with no o
//Replace 5 with s
pass4 = p.permute("pa55word");
}
So to me, it seems im on the right track, but I can see that im actually going to be missing some of these sets and then im not going to crack the password.I need to use the results of the previous set somehow.
In the above im never going to get a value of say P#55w0rd, and that could be the correct answer.
Ok so after some scraping around and head scratching - I came up with this, and it works!Well I was able to brute force the target site and received my success message!
public static List<string> Combinations(string input)
{
var combinations = new List<string>();
combinations.Add(input);
int n = input.Length;
// Number of permutations is 2^n
int max = 1 << n;
for (int i = 0; i < input.Length; i++)
{
char[] buffer = input.ToArray();
if (buffer[i] == 'o')
{
buffer[i] = '0';
combinations.Add(new string(buffer));
combinations = combinations.Concat(Combinations(new string(buffer))).ToList();
}
if (buffer[i] == 'a')
{
buffer[i] = '#';
combinations.Add(new string(buffer));
combinations = combinations.Concat(Combinations(new string(buffer))).ToList();
}
if (buffer[i] == 's')
{
buffer[i] = '5';
combinations.Add(new string(buffer));
combinations = combinations.Concat(Combinations(new string(buffer))).ToList();
}
}
for (int i = 0; i < max; i++)
{
char[] combination = input.ToCharArray();
// If j-th bit is set, we
// convert it to upper case
for (int j = 0; j < n; j++)
{
if (((i >> j) & 1) == 1)
combination[j] = (char)(combination[j] - 32);
//if (((i >> j) & 1) == 2)
// combination[j] = (char)(combination[j] - 32);
}
string tmp = new string(combination);
bool add = true;
foreach (char c in combination)
{
if (((c) == 32) || (c) == 16 || (c) == 21) //add 0 and 5
{
//dont add
add = false;
//break on first instance
break;
}
else
{
add = true;
}
}
if (add) combinations.Add(tmp);
}
return combinations;
}

How do I generate a random alphanumeric array that has 3 letter and 6 digits in c#?

I am trying to generate a random alphanumeric array that consist of 3 letters and 6 digits. The entire array must be random. The only way I could think of is generating 2 individual random arrays and then merging them and randomizing the merged array. Any help would be appreciated. I specifically need help on ensuring that the correct number of variable types are stored. Here is my semi-working code:
static void Main(string[] args)
{
var alphabetic = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var numeric = "0123456789";
var stringChars = new char[9];
var random = new Random();
for (int i = 0; i < 3; i++)
{
stringChars[i] = alphabetic[random.Next(alphabetic.Length)];
}
for(int i = 3; i< stringChars.Length; i++)
{
stringChars[i] = numeric[random.Next(numeric.Length)];
}
var ranChars = new char[9];
var semisorted = new String(stringChars);
for (int i=0; i< ranChars.Length; i++)
{
ranChars[i] = semisorted[random.Next(semisorted.Length)];
}
var final = new string(ranChars);
Console.WriteLine("{0}", final);
Console.ReadLine();
}
You're close. But the problem here is that you're selecting randomly from the "semi-sorted" array, while what's really necessary at that point is picking a random permutation. One way to do that is with a Fisher-Yates shuffle.
So combining that with the code you had that worked: (not tested)
for (int i = 0; i < 3; i++)
{
stringChars[i] = alphabetic[random.Next(alphabetic.Length)];
}
for(int i = 3; i< stringChars.Length; i++)
{
stringChars[i] = numeric[random.Next(numeric.Length)];
}
int n = stringChars.Length;
while (n > 1)
{
int k = random.Next(n--);
char temp = stringChars[n];
stringChars[n] = stringChars[k];
stringChars[k] = temp;
}
string result = new string(stringChars);
Harold's answer is way cleaner, but here's another approach for the whole '100 ways to do the same thing in programming' concept. [Edit: Doh, I reversed the number of digits and letters. Here's a fix:]
public static void Main(string[] args)
{
var random = new Random();
var finalString = string.Empty;
var finalArray = new string[9];
for (var i = 0; i < 3; i++)
{
var alphabet = random.Next(0, 26);
var letter = (char) ('a' + alphabet);
finalArray[i] = letter.ToString().ToUpper();
}
for (var i = 3; i < 9; i++)
{
var number = random.Next(0, 9);
finalArray[i] = number.ToString();
}
var shuffleArray = finalArray.OrderBy(x => random.Next()).ToArray();
for (var i = 0; i < finalArray.Length; i++)
{
finalString += shuffleArray[i];
}
Console.WriteLine(finalString);
Console.ReadKey();
}

random uppercase in a word + multiple string insert

I really need a solution for the next scenario(I've been searching for hours and beating about the bushes to find a smooth solution, but none worked):
I have a winform that:
parse a text file
generate some folders using random words from that file
My code so far:
int value;
string path = null;
private void button1_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
if (fbd.ShowDialog(this) == DialogResult.OK)
{
path = fbd.SelectedPath;
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
value = Convert.ToInt32(textBox1.Text);//store the value from the textbox in variable "value"
}
private void button2_Click(object sender, EventArgs e)
{
if (path != null && Directory.Exists(path))
for (int i = 0; i < value; i++)
{
Random rnd = new Random();
string tick1 = rnd.Next(0, 10).ToString();
var lines = File.ReadAllLines(#"M:\\dictionar.txt");
var r = new Random(DateTime.Now.Millisecond);
var randomLineNumber = r.Next(0, lines.Length - 1);
var line = lines[randomLineNumber];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 3 == 2)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, string.Format("{0}", line.Insert(2, tick1).Insert(4, tick1).Insert(6, tick1))));
}
}
Is there a way to use ToUpper() method as line.Insert() one so that I can get random upper letters? More, is there a better way of randomizing those index positions form line.Insert() (I'm asking this because when it's generating the folders name: the indexes are the same: e.g pe8rs8on8al and just after that the index changes.)?
I want to achieve the following:
if I have the next words in the .txt file:
personal
football
programming
computer
I would like the folder names to look like:
Pe3rs9oN1al
fO8ot5Ba6lL
You can loop through the characters in the string and build a new string depending on random values:
StringBuilder b = new StringBuilder();
for (int i = 0; i < line.Length; i++ ) {
char c = line[i];
if (rnd.Next(2) == 0) {
c = Char.ToUpper(c);
}
b.Append(c);
if (i % 2 == 1) {
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Note: You shouldn't create Random objects in the loop. You should create a single Random object before the loop and use for all random numbers that you need. Creating instances too close in time will make them return the same sequences of random numbers. Also, you don't need to seed the random generator from the clock, the constructor without parameters does that automatically:
Random rnd = new Random();
So, the code in the method would be:
if (path != null && Directory.Exists(path))
Random rnd = new Random();
for (int i = 0; i < value; i++)
{
var lines = File.ReadAllLines(#"M:\\dictionar.txt");
var randomLineNumber = rnd.Next(0, lines.Length);
var line = lines[randomLineNumber];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 2 == 1)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, line));
}
}
Note the rnd.Next(0, lines.Length) to pick a random line. The upper limit for the random number is not inclusive, so if you use rnd.Next(0, lines.Length - 1) it will never pick the last line.
That's because you are specifying only tick1 in the same loop. If you want to change this, add additional ticks to your code as below:
string tick1 = rnd.Next(0, 10).ToString();
string tick2 = rnd.Next(0, 10).ToString();
string tick3 = rnd.Next(0, 10).ToString();
Then use those in your formatting of the string:
Directory.CreateDirectory(Path.Combine(path, string.Format("{0}", line.Insert(2, tick1).Insert(4, tick2).Insert(6, tick3))))
Like Guffa said you should not use Random in a loop, in all preference you should only instanciate one of it, but I think you could use it like this
public static class StringRandomize
{
static readonly Random rnd = new Random();
static char[] permmitedCharacters { get; set; }
static StringRandomize()
{
List<char> Chars= new List<char>();
for (int i = 48; i < 48+10; i++)
{
Chars.Add((char)i);
}
for (int i = 65; i < 65+26; i++)
{
Chars.Add((char)i);
}
permmitedCharacters = Chars.ToArray();
}
public static string Randomize(string input, double RandomizePercent = 30)
{
StringBuilder result = new StringBuilder();
int index = 0;
while (index < input.Length)
{
if (rnd.Next(0, 100) <= RandomizePercent)
{
if (rnd.Next(0, 100) <= RandomizePercent)
{
result.Append(GenerateCaracter());
}
else
{
if (rnd.Next(0, 100) > 50)
{
result.Append(input.ToLower()[index]);
}
else
{
result.Append(input.ToUpper()[index]);
}
index++;
}
}
else
{
result.Append(input[index]);
index++;
}
}
return result.ToString();
}
private static char GenerateCaracter()
{
return permmitedCharacters[rnd.Next(0, permmitedCharacters.Length)];
}
}
private static void GenerateRandomDirectories(string path, int value)
{
//I'm supposing value is the number of lines that you want
var lines = File.ReadAllLines(#"M:\\dictionar.txt");
Random rnd = new Random();
if (path != null && Directory.Exists(path))
{
for (int i = 0; i < value; i++)
{
Directory.CreateDirectory(path + "\\" + StringRandomize.Randomize(lines[rnd.Next(0,lines.Length)]));
}
}
}
"pers3o7Nal"
"foOtBaLl"
Got like this
public Form1()
{
InitializeComponent();
string content = "";
using (FileStream fs = new FileStream("D:\\names.txt", FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs))
content = sr.ReadToEnd();
string[] names = content.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
string path = "D:\\RandDirs";
if (!Directory.Exists(path))Directory.CreateDirectory(path) ;
for (int i = 0; i < 50; i++) Directory.CreateDirectory(path + "\\" + getRandomName(names));
}
Random randName = new Random();
Random insertingNumber = new Random();
Random randUpper = new Random();
Random randInsertNumber = new Random();
string getRandomName(string[] names)
{
string name = names[randName.Next(names.Length)];
name = name.Replace(" ", "");
string result = "";
for (int i = 0; i < name.Length; i++)
result += (randUpper.Next(0, 9) <= 5 ? name[i].ToString().ToLower() : name[i].ToString().ToUpper())
+ (((i + 1) % 2 == 0) ? insertingNumber.Next(0, 9).ToString() : "");
return result;
}
as per your needs, i've changed from randomly inserting numbers to inserting number every 2 characters.

Categories