Brute Force Algorithm Prints Only 0 - c#

I am creating a Brute Force Algorithm (for educational purposes) on C#, and I have met an error.
My way of bruteforce is like a clock - last character in the string goes up from 0 to last character in a character array set in the beggining of the program, when it reaches the end - resets to 0 and increases the previous character by 1 and so on.
Yet, the code below prints only 0's:
// Array with characters to use in Brute Force Algorithm.
// You can remove or add more characters in this array.
private static char[] fCharList =
{
'0','1','2','3','4','5','6','7','8','9','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','A','B','C','D','E','F','G','H','I','J','C','L','M','N','O','P',
'Q','R','S','T','U','V','X','Y','Z','~','!','#','#','$','%','^','&','*','(',')','[',']','{','}','.',',','/','?','\'','|','"',';',':','<','>','\\','=','-','+','`','_'
};
private static String password;
static void Main(string[] args)
{
Console.WriteLine("Enter the password: ");
password = Console.ReadLine();
Bruteforce();
}
// The Bruteforce algorithm
// Goes like a clock cycle: Last index goes from fCharList[0] to fCharList[fCharList.Length - 1]
// then resets and last index -1 increases and so on.
public static String Bruteforce()
{
String currPass = fCharList[0].ToString();
bool foundPass = false;
for (int i = 1; !foundPass; i++)
{
// If there's a need to increase (foundd fCharList[fCharList.Length - 1] in the String)
if (currPass.Contains(fCharList[fCharList.Length - 1]))
{
//If no need to increase the whole length and reset all the characters
if (!(currPass.IndexOf(fCharList[fCharList.Length - 1]) == 0))
{
String updateCurrPass = "";
for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
updateCurrPass += fCharList[0].ToString();
}
currPass.Insert(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt<char>(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1)) + 1].ToString() + updateCurrPass);
}
}
else // If no cycle ended - continue increasing last "digit"
{
currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}
Console.Write(currPass + " ");
}
return "";
}
I tried all the possible issues with the currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString()); (as I suspected that the problem might occure in the printing process itself), but with no success.
I also tried to trace the code using breakpoints and paper, still nothing.
It would be very pleasing if someone can help me solve this problem.
Edit:
Below, many suggested the updateCurrPass += fCharList[0].ToString(); should rather be updateCurrPass += fCharList[j].ToString();. I haven't yet checked that option too deep, but to explain better my situation, I want it to work like a clock cycle - when the last digit is the latest character in fCharList, the previous digit increases and so on. The code mentioned resets the digits that have reached the last character. (So, if the string currPass was "0aa___" (_ is the last character), it will become 0ab000) the updateCurrPass adds the 3 0's, while the rest of the the function increases the a to b.

As noted by #VincentElbertBudiman, you have to use j in your loop and not 0. (or maybe not, I'm unsure if I understand well your algorithm)
But there's something more:
You have to note that in C#, Strings are immutable, meaning currPass.Insert(...) does nothing in itself, you have to reassign the result like currPass = currPass.Insert(...);
But hey, I think you are overcomplicating the algorithm.
What I would've done:
string currPass = fCharList[0].ToString();
bool found = false;
while(!found)
{
currPass = IncreasePassword(currPass);
found = CheckPass(currPass);
}
With IncreasePassword:
public static string IncreasePassword(string pass)
{
bool changed = false;
StringBuilder sb = new StringBuilder(pass);
// loop through pass until we change something
// or we reach the end (what comes first)
for(int i = 0; i < pass.Length && !changed; i++)
//for(int i = pass.Length - 1; i >= 0 && !changed; i--)
{
int index = Array.IndexOf(fCharList, sb[i]);
// if current char can be increased
if(index < fCharList.Length - 1)
{
// if we have __012 then we'll go on 00112
// so here we replace the left __ with 00
for(int j = i - 1; j >= 0 && sb[j] == fCharList[fCharList.Length - 1]; j--)
//for(int j = i + 1; j < sb.Length && sb[j] == fCharList[fCharList.Length - 1]; j++)
{
sb[j] = fCharList[0];
}
// and here we increase the current char
sb[i] = fCharList[index + 1];
changed = true;
}
}
// if we didn't change anything, it means every char were '_'
// so we start with a fresh new full-of-0 string
if(!changed)
{
return "".PadLeft(pass.Length + 1, fCharList[0]);
}
return sb.ToString();
}
Live example.
Explanations
This will work from left to right the following way:
Say our fCharList is { '0','1','2' } for simplifications.
We'll have:
0
1
2
00
10
20
01
11
21
02
12
22
000
100
200
010
110
210
020
....
Test results
This is what it gives with reversed inputs (as my solution goes the other way around) from Weeble's suggestions:
Input Output
0 1
1 2
P Q
_ 00
00 10
_0 01
__CBA 00DBA
____ 00000
Please note that your fCharList is broken as there's a C instead of K!

Did you think because you assign updateCurrPass like this ? :
for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
updateCurrPass += fCharList[0].ToString();
}
I think it should be involving j or something :
for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
updateCurrPass += fCharList[j].ToString();
}
Added code :
This below code will do nothing because the function will return the function (instead of changing the object passed by parameters), you should add currPass = currPass.Insert(...) as noted by #Rafalon
else // If no cycle ended - continue increasing last "digit"
{
currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}
Use this instead :
else // If no cycle ended - continue increasing last "digit"
{
currPass = currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}

While there are specific problems pointed out by the other answers, may I suggest that your broader problem is that you're trying to do too much at once? You may well be capable of writing this whole algorithm in one piece and tweaking it until it works, but it's both very hard to do this and hard to have confidence in the end that it's correct. You will find it easier to break down the algorithm into smaller functions and test those individually to confirm they do what you expect.
For example, you could break out the part of the algorithm that works out "given the last password I checked, what is the next password in sequence to consider"? This is the core of the algorithm, and it can be separated from the work of iterating through all the possible passwords and testing them against the current one. And it is much easier to test! For example, you can use test data like this:
Input Expected output
"0" "1"
"1" "2"
"P" "Q"
"_" "00"
"00" "01"
"0_" "10"
"ABC__" "ABD00"
"____" "00000"
When you find out that your function doesn't give the right answer for some or all of these tests, you have a much smaller and more specific job to do to figure out what's wrong than trying to debug the whole algorithm at once.

Related

Missing characters after string concatenate

I am having a problem whereby the letter at the position(e.g 39) would be replaced with the text I wanted to input. However what I want was to insert the text at position 39 instead of replacing it. Anyone please guide me on this.
string description = variables[1]["value"].ToString();// where I get the text
int nInterval = 39;// for every 39 characters in the text I would have a newline
string res = String.Concat(description.Select((c, z) => z > 0 && (z % nInterval) == 0 ? Environment.NewLine +"Hello"+(((z/ nInterval)*18)+83).ToString()+"world": c.ToString()));
file_lines = file_lines.Replace("<<<terms_conditions>>>",resterms); //file_lines is where I read the text file
Original text
Present this redemption slip to receive: One
After String.Concat
Present this redemption slip to receive\r\n\u001bHello101world
One //: is gone
I am also having a issue where I want to put a new line if it contains * in the text. If anybody is able to help that would be great.
Edit:
What I want to achieve is something like this
Input
*Item is considered paid if unsealed.*No replacement or compensation will be given for any expired coupons.
so like i need to find every 39 character and also * to input newline so it will be
Output
*Item is considered paid if unsealed.
*No replacement or compensation will be
given for any expired coupons.
Try String.Insert(Int32, String) Method
Insert \n where you need new line.
If I understood your question properly, you want a newline after every 39 characters. You can use string.Insert(Int32, String) method for that.
And use String.Replace(String, String) for your * problem.
Below code snippet doing that using a simple for loop.
string sampleStr = "Lorem Ipsum* is simply..";
for (int i = 39; i < sampleStr.Length; i = i + 39){
sampleStr = sampleStr.Insert(i, Environment.NewLine);
}
//sampleStr = sampleStr.Replace("*", Environment.NewLine);
int[] indexes = Enumerable.Range(0, sampleStr.Length).Where(x => sampleStr[x] == '*').ToArray();
for (int i = 0; i < indexes.Length; i++)
{
int position = indexes[i];
if (position > 0) sampleStr = sampleStr.Insert(position, Environment.NewLine);
}
If you want to do both together
int[] indexes = Enumerable.Range(0, sampleStr.Length).Where(x => sampleStr[x] == '*' || x % 39 == 0).ToArray();
int j = 0;
foreach (var position in indexes)
{
if (position > 0)
{
sampleStr = sampleStr.Insert(position + j, Environment.NewLine);
j = j + 2; // increment by two since newline will take two chars
}
}
Without debating the method chosen to achieve the desired result, the problem with the code is that at the 39th character it adds some text, but the character itself has been forgotten.
Changing the following line should give the expected output.
string res = String.Concat(description.Select((c, z) => z > 0 && (z % nInterval) == 0 ? Environment.NewLine + "Hello" + (((z / nInterval) * 18) + 83).ToString() + "world" + c.ToString() : c.ToString()));
<== UPDATED ANSWER BASED ON CLARIFICATION IN QUESTION ==>
This will do what you want, I believe. See comments in line.
var description = "*Item is considered paid if unsealed.*No replacement or compensation will be given for any expired coupons.";
var nInterval = 39; // for every 39 characters in the text I would have a newline
var newline = "\r\n"; // for clarity in the Linq statement. Can be set to Environment.Newline if desired.
var z = 0; // we'll handle the count manually.
var res = string.Concat(
description.Select(
(c) => (++z == nInterval || c == '*') // increment z and check if we've hit the boundary OR if we've hit a *
&& ((z = 0)==0) // resetting the count - this only happens if the first condition was true
? newline + (c == ' ' ? string.Empty : c.ToString()) // if the first character of a newline is a space, we don't need it
: c.ToString()
));
Output:
*Item is considered paid if unsealed.
*No replacement or compensation will be
given for any expired coupons.

String.Substring() crashes with certain inputs

I trying to split a string with Substring(), and I am having a problem I keep getting crashes with certin values.The problematic lane is(according to the "debugging" i tried):
string sub = str.Substring(beg,i);
and the whole code is :
static void Prints(string str)
{
int beg = 0;
for (int i = 0; i < str.Length; i++)
{
if (str[i] == '*')
{
Console.WriteLine(i);
//Console.WriteLine("before");
string sub = str.Substring(beg,i);
//Console.WriteLine("after");
beg = i+1;
if (sub.Length % 2 == 0)
{
Console.WriteLine(sub.Length/2);
int n = sub.Length / 2;
Console.WriteLine("{0} {1}", sub[n-1], sub[n]);
}
else
{
int n = sub.Length / 2;
Console.WriteLine(sub[n]);
}
The eror happens when the input is :
hi*its*
thats the output:
h i
Unhandled Exception: 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 _39.Program.Prints(String str) in D:\12\39\Program.cs:line 36
at _39.Program.Main(String[] args) in D:\12\39\Program.cs:line 13
I know there might be a better way using split() but I still want to understand what cause the eror.
Thanks in advance
Doron.
The problem is that you're not subtracting the distance you are into the string from the overall length.
If you look at the debug output you will find that:
str.Substring(3, 1) = "i"
str.Substring(3, 2) = "it"
str.Substring(3, 3) = "its"
str.Substring(3, 4) = "its*"
str.Substring(3, 5) = // Error! You're beyond the end of the string.
So clearly you are attempting to pull (in your example) 6 characters from the string starting at position 3. This would require an input string with total length 10 or more (as substring is Zero Index based). Your input string is only 7 chars long.
Try tokenizing your string. As soon as you try manually tokenizing using indices and counting things go wrong. Tokenizing is a god send :)
Good Luck!

Find matching word in C#

I'm facing a problem to solve this issue. I'm having a string variable, for an example
string text="ABCD,ABCDABCD,ADCDS";
I need to search a string value like 'BC' into above string and find the position where "BC" occur. i.e if we search "BC" in to that string variable it will bring the output as 1,6
0 1 2 3 4 5 6 7 8 9 10 11 12 13
-------------------------------------------------------
| A | B | C | D | , | A | B | C | D | , | A | D | C | S |
-------------------------------------------------------
The problem is we cant use built in string class methods contains(), lastIndexOf(). can anyone help me to do this?
The problem is we cant use built in string class methods
'contains()','lastIndexOf()'. can anyone help me to do this?
Then you can built your own. I assume that even Substring is forbidden.
string text="ABCD,ABCDABCD,ADCDS";
string whatToFind = "BC";
List<int> result = new List<int>();
for(int index=0; index < text.Length; index++)
{
if(index + whatToFind.Length > text.Length)
break;
bool matches = true;
for(int index2=0; index2<whatToFind.Length; index2++)
{
matches = text[index+index2] == whatToFind[index2];
if(!matches)
break;
}
if(matches)
result.Add(index);
}
Here's the running code: http://ideone.com/s7ej3
Probably you can't use regural expression in your homework. The best solution is think about your string as char array. Read about http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
Rolling your own version of IndexOf is not hard (as per the answers you've already received), and since it's homework, you can probably get away with it.
However, as you can probably imagine, a simple for loop is not the most efficient way to do it. String searching is an important topic, and although you won't probably need to implement it outside of homework ever again, you can read about it for your own edification.
string text = "ABCD,ABCDABCD,ADCDS";
int location;
for (int i = 0; i < text.Length; i++)
if (text[i] == 'B')
if (text[i + 1] == 'C')
{
location = i;
i++;
}
EDIT:
List<int> locations = new List<int>();
string text = "ABCD,ABCDABCD,ADCDS";
for (int i = 0; i < text.Length; i++)
if (text[i] == 'B')
if (text[i + 1] == 'C')
{
location.Add(i);
i++;
}
This should work out for you:
string text="ABCD,ABCDABCD,ADCDS";
var seekindex = 0;
var positions = new List<int>();
while( seekindex < text.Length ){
var index = text.IndexOf( "BC", seekindex);
if( index > -1){
positions.Add(index);
seekindex = index + 1;
}else{
break;
}
}
This uses the IndexOf method with a startindex to make sure that we continue searhing from our previous hit location the next time, and untill IndexOf returns -1 indication no more hits.
positions will contain the indexes at the end, and the result is actually 1,6,10 and not 1,6 ;)
EDIT
Just realized he could not use IndexOf. Trying again :)
string text="ABCD,ABCDABCD,ADCDS";
var positions = new List<int>();
for( int i = 0; i < text.Length-1; i++ ){
if( text[i] == 'B' && text[i+1] == 'C' ){
positions.Add(i);
}
}
It might seem like a preformance problem here since the if sentence checks both the current, and the next char, and therefore checking all chars twice.
But in fact it wont. Because of the AND (&&) in between, if text[i] is not B, it will not perform the second check since it knows that the if will fail anyway.
Below is a perfectly working example to your requirements, but is also nice and slow and also has a big memory footprint:
string text = "ABCD,ABCDABCD,ADCDS";
string whatToFind = "BC";
string delim = "";
for(int index=0; index < text.Length; index++)
{
if(index + whatToFind.Length > text.Length)
break;
if(text.SubString(index, whatToFind.Length) == whatToFind)
{
Console.Out.WriteLine(delim + index.ToString())
delim = ",";
}
}
I leave it to the reader as an exercise to improve the performance and memory usage. It's more useful to understand where and why this is slow than to achieve a faster answer.

erroneous character fixing of strings in c#

I have five strings like below,
ABBCCD
ABBDCD
ABBDCD
ABBECD
ABBDCD
all the strings are basically same except for the fourth characters. But only the character that appears maximum time will take the place. For example here D was placed 3 times in the fourth position. So, the final string will be ABBDCD. I wrote following code, but it seemed to be less efficient in terms of time. Because this function can be called million times. What should I do to improve the performance?
Here changedString is the string to be matched with other 5 strings. If Any position of the changed string is not matched with other four, then the maxmum occured character will be placed on changedString.
len is the length of the strings which is same for all strings.
for (int i = 0; i < len;i++ )
{
String findDuplicate = string.Empty + changedString[i] + overlapStr[0][i] + overlapStr[1][i] + overlapStr[2][i] +
overlapStr[3][i] + overlapStr[4][i];
char c = findDuplicate.GroupBy(x => x).OrderByDescending(x => x.Count()).First().Key;
if(c!=changedString[i])
{
if (i > 0)
{
changedString = changedString.Substring(0, i) + c +
changedString.Substring(i + 1, changedString.Length - i - 1);
}
else
{
changedString = c + changedString.Substring(i + 1, changedString.Length - 1);
}
}
//string cleanString = new string(findDuplicate.ToCharArray().Distinct().ToArray());
}
I'm not quite sure what you are going to do, but if it is about sorting strings by some n-th character, then the best way is to use Counting Sort http://en.wikipedia.org/wiki/Counting_sort It is used for sorting array of small integers and is quite fine for chars. It has linear O(n) time. The main idea is that if you know all your possible elements (looks like they can be only A-Z here) then you can create an additional array and count them. For your example it will be {0, 0, 1 ,3 , 1, 0,...} if we use 0 for 'A', 1 for 'B' and so on.
There is a function that might help performance-wise as it runs five times faster. The idea is to count occurrences yourself using a dictionary to convert character to a position into counting array, increment value at this position and check if it is greater than previously highest number of occurrences. If it is, current character is top and is stored as result. This repeats for each string in overlapStr and for each position within the strings. Please read comments inside code to see details.
string HighestOccurrenceByPosition(string[] overlapStr)
{
int len = overlapStr[0].Length;
// Dictionary transforms character to offset into counting array
Dictionary<char, int> char2offset = new Dictionary<char, int>();
// Counting array. Each character has an entry here
int[] counters = new int[overlapStr.Length];
// Highest occurrence characters found so far
char[] topChars = new char[len];
for (int i = 0; i < len; ++i)
{
char2offset.Clear();
// faster! char2offset = new Dictionary<char, int>();
// Highest number of occurrences at the moment
int highestCount = 0;
// Allocation of counters - as previously unseen character arrives
// it is given a slot at this offset
int lastOffset = 0;
// Current offset into "counters"
int offset = 0;
// Small optimization. As your data seems very similar, this helps
// to reduce number of expensive calls to TryGetValue
// You might need to remove this optimization if you don't have
// unused value of char in your dataset
char lastChar = (char)0;
for (int j = 0; j < overlapStr.Length; ++ j)
{
char thisChar = overlapStr[j][i];
// If this is the same character as last one
// Offset already points to correct cell in "counters"
if (lastChar != thisChar)
{
// Get offset
if (!char2offset.TryGetValue(thisChar, out offset))
{
// First time seen - allocate & initialize cell
offset = lastOffset;
counters[offset] = 0;
// Map character to this cell
char2offset[thisChar] = lastOffset++;
}
// This is now last character
lastChar = thisChar;
}
// increment and get count for character
int charCount = ++counters[offset];
// This is now highestCount.
// TopChars receives current character
if (charCount > highestCount)
{
highestCount = charCount;
topChars[i] = thisChar;
}
}
}
return new string(topChars);
}
P.S. This is certainly not the best solution. But as it is significantly faster than original I thought I should help out.

What is the most efficient way to detect if a string contains a number of consecutive duplicate characters in C#?

For example, a user entered "I love this post!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
the consecutive duplicate exclamation mark "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" should be detected.
The following regular expression would detect repeating chars. You could up the number or limit this to specific characters to make it more robust.
int threshold = 3;
string stringToMatch = "thisstringrepeatsss";
string pattern = "(\\d)\\" + threshold + " + ";
Regex r = new Regex(pattern);
Match m = r.Match(stringToMatch);
while(m.Success)
{
Console.WriteLine("character passes threshold " + m.ToString());
m = m.NextMatch();
}
Here's and example of a function that searches for a sequence of consecutive chars of a specified length and also ignores white space characters:
public static bool HasConsecutiveChars(string source, int sequenceLength)
{
if (string.IsNullOrEmpty(source))
return false;
if (source.Length == 1)
return false;
int charCount = 1;
for (int i = 0; i < source.Length - 1; i++)
{
char c = source[i];
if (Char.IsWhiteSpace(c))
continue;
if (c == source[i+1])
{
charCount++;
if (charCount >= sequenceLength)
return true;
}
else
charCount = 1;
}
return false;
}
Edit fixed range bug :/
Can be done in O(n) easily: for each character, if the previous character is the same as the current, increment a temporary count. If it's different, reset your temporary count. At each step, update your global if needed.
For abbccc you get:
a => temp = 1, global = 1
b => temp = 1, global = 1
b => temp = 2, global = 2
c => temp = 1, global = 2
c => temp = 2, global = 2
c => temp = 3, global = 3
=> c appears three times. Extend it to get the position, then you should be able to print the "ccc" substring.
You can extend this to give you the starting position fairly easily, I'll leave that to you.
Here is a quick solution I crafted with some extra duplicates thrown in for good measure. As others pointed out in the comments, some duplicates are going to be completely legitimate, so you may want to narrow your criteria to punctuation instead of mere characters.
string input = "I loove this post!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!aa";
int index = -1;
int count =1;
List<string> dupes = new List<string>();
for (int i = 0; i < input.Length-1; i++)
{
if (input[i] == input[i + 1])
{
if (index == -1)
index = i;
count++;
}
else if (index > -1)
{
dupes.Add(input.Substring(index, count));
index = -1;
count = 1;
}
}
if (index > -1)
{
dupes.Add(input.Substring(index, count));
}
The better way i my opinion is create a array, each element in array is responsible for one character pair on string next to each other, eg first aa, bb, cc, dd. This array construct with 0 on each element.
Solve of this problem is a for on this string and update array values.
You can next analyze this array for what you want.
Example: For string: bbaaaccccdab, your result array would be { 2, 1, 3 }, because 'aa' can find 2 times, 'bb' can find one time (at start of string), 'cc' can find three times.
Why 'cc' three times? Because 'cc'cc & c'cc'c & cc'cc'.
Use LINQ! (For everything, not just this)
string test = "aabb";
return test.Where((item, index) => index > 0 && item.Equals(test.ElementAt(index)));
// returns "abb", where each of these items has the previous letter before it
OR
string test = "aabb";
return test.Where((item, index) => index > 0 && item.Equals(test.ElementAt(index))).Any();
// returns true

Categories

Resources