I've seen few implementations of variations of string in C#, but none of them had any limitation on their length. Unfortunately, I cannot modify them to achieve my goal which is e.g.
for:
string = "ABCD" and variationLength = 2
generate new strings:
AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC
I'm looking for exactly this Python's itertools.permutations implementation but in C#. (https://docs.python.org/3/library/itertools.html#itertools.permutations)
Is there anything similar to its in C#? If not, then what is the easiest way to implement it?
Edit_2:
so far I came up with an idea to list all unique chars of given string and then get variations out of them
static void PrintAllKLengthPerm(string str, int k)
{
int n = str.Length;
PrintAllKLengthPermRec(str, "", n, k);
}
// The main recursive method to print all possible strings of length k
static void PrintAllKLengthPermRec(string str, String prefix, int n, int k)
{
// Base case: k is 0, print prefix
if (k == 0)
{
Console.WriteLine(prefix);
return;
}
// One by one add all characters from str and recursively
// call for k equals to k-1
for (int i = 0; i < n; ++i)
{
// Next character of input added
String newPrefix = prefix + str[i];
// k is decreased, because we have added a new character
PrintAllKLengthPermRec(str, newPrefix, n, k - 1);
}
}
static void Main(string[] args)
{
string str = "ABCD";
int permLen = 2;
//get all unique characters in string
string uniqStr = new String(str.Distinct().ToArray());
// Print all possible strings of length permLen out of uniqStr characters
PrintAllKLengthPerm(uniqStr, permLen);
}
However I am looking for more optimal and effective solution
Here's a truly recursive permutation method:
public IEnumerable<string> Permutate(string source, int count)
{
if (source.Length == 1)
{
yield return source;
}
else if (count == 1)
{
for (var n = 0; n < source.Length; n++)
{
yield return source.Substring(n, 1);
}
}
else
{
for (var n = 0; n < source.Length; n++)
foreach (var suffix in Permutate(
source.Substring(0, n)
+ source.Substring(n + 1, source.Length - n - 1), count -1))
{
yield return source.Substring(n, 1) + suffix;
}
}
}
It can be called with Permutate("ABCD", 2) and returns this:
I made the following recursive function which accomplishes your task:
static void Permutations(List<string> output, string str, int n, string curr)
{
if(curr.Length == n)
{
output.Add(curr);
return;
}
foreach(char c in str)
if(!curr.Contains(c.ToString()))
Permutations(output, str, n, curr + c.ToString());
}
and then you call it like this:
string str = "ABCD";
int length = 2;
List<string> perms = new List<string>();
Permutations(perms, str, length, "");
// now the list "perms" will contain the permutations of "str" in length "n"
List<string> newPermutations = new List<string>();
for(int a = 0; a!=inString.Count; a++)
for((int b = 0; b!=inString.Count; b++)
if(noRepetitions && a == b) continue;
newPermutations.Add(""+inString[a] + inString[b]);
I think that that should work; I am still trying to figure out a way to not only have 2 letters.
Edit: Edited it to work, the old one just didn't work... lol
Edit: Thanks to #Bloopy, they helped me spot some errors in my for loops
Here's a solution using modulo and division. There are 4² possible strings of length 2 using the letters ABCD. Number them from 0 to 4²-1 and repeatedly divide each number by 4. Use the resulting remainders as array indexes on the ABCD string.
This has the advantage of allowing you to keep the strings with repeated elements (AA, BB, CC, DD) when needed – just skip the discard step.
string alphabet = "ABCD";
int length = 2;
int[] indexes = new int[length];
char[] item = new char[length];
// loop through all possible strings for the given alphabet and length
for (int i = 0; i < Math.Pow(alphabet.Length, length); i++) {
int dividend = i;
for (int j = length - 1; j >= 0; j--) {
indexes[j] = dividend % alphabet.Length;
dividend /= alphabet.Length;
}
// discard any that use the same alphabet element more than once
if (indexes.Distinct().Count() < length)
continue;
for (int k = 0; k < length; k++) {
item[k] = alphabet[indexes[k]];
}
Console.WriteLine(item);
}
Alternatively, here's a really brief solution using LINQ. Note that this one doesn't work correctly if there are duplicate elements in the string (unless you want to remove the call to Where and keep the AA, BB etc.). I'd need to track the indexes like I did in my method above.
IEnumerable<string> prm = alphabet.Select(c => c.ToString());
for (int a = 1; a < length; a++)
prm = prm.SelectMany(s => alphabet.Where(t => !s.Contains(t)), (x, y) => x + y);
foreach (string s in prm)
Console.WriteLine(s);
Related
Lets suppose i have two strings string1 and string2.
var string1 = "images of canadian geese goslings";
var string2 = "Canadian geese with goslings pictures to choose from, with no signup needed";
I need to find biggest substring of string1 which matches in string2.
here biggest substring will be "canadian geese" which is matching in string2.
How can I find it? I tried breaking string1 into char[] and find words then merged matched words but that failed my objective.
classy loop approach - the result includes te space after geese "canadian geese "
var string1 = "images of canadian geese goslings";
var string2 = "Canadian geese with goslings pictures to choose from, with no signup needed";
string result = "";
for (int i = 0; i < string1.Length; i++)
{
for (int j = 0; j < string1.Length - i; j++)
{
//add .Trim() here if you want to ignore space characters
string searchpattern = string1.Substring(i, j);
if (string2.IndexOf(searchpattern, StringComparison.OrdinalIgnoreCase) > -1 && searchpattern.Length > result.Length)
{
result = searchpattern;
}
}
}
https://dotnetfiddle.net/q3rHjI
Side note:
canadian and Canadian are not equal so you have to use StringComparison.OrdinalIgnoreCase if you want to search case insensitive
Have a look at the following code https://dotnetfiddle.net/aPyw3o
public class Program {
static IEnumerable<string> substrings(string s, int length) {
for (int i = 0 ; i + length <= s.Length; i++) {
var ss = s.Substring(i, length);
if (!(ss.StartsWith(" ") || ss.EndsWith(" ")))
yield return ss;
}
}
public static void Main()
{
int count = 0;
var string1 = "images of canadian geese goslings";
var string2 = "Canadian geese with goslings pictures to choose from, with no signup needed";
string result = null;
for (int i = string1.Length; i>0 && string.IsNullOrEmpty(result); i--) {
foreach (string s in substrings(string1, i)) {
count++;
if (string2.IndexOf(s, StringComparison.CurrentCultureIgnoreCase) >= 0) {
result = s;
break;
}
}
}
if (string.IsNullOrEmpty(result))
Console.WriteLine("no common substrings found");
else
Console.WriteLine("'" + result + "'");
Console.WriteLine(count);
}
}
The substrings method returns all substrings of the string s with the length of length (for the yield have a look at the documentation https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/yield) We skip substrings that start or end with a space, as we don't want whitespaces to make a substring longer than it really is)
The outer loop iterates through all the possible length values for the substrings, from the longest (ie string1.Length) to the shortest (ie 1). Then for each of the found substrings of length i is checked, if it's also a substring of string2. If that's the case, we can stop, as there cannot be any longer common substring, because we checked all longer substrings in previous iterations. But of course there may be other common substrings with length i
I'm going to add one more, using span/readonlymemory so you can avoid allocating all the strings that the current answers create. Note I didn't do any check for starting space or ending space as that does not seem to be a requirement for the question. This does do a case insensitive search, if you don't want that you can make it more efficient by using the built in indexof and dropping the case insensitive compares.
static void Main(string[] _)
{
var string1 = "images of canadian geese goslings";
var string2 = "Canadian geese with goslings pictures to choose from, with no signup needed";
var longest = FindLongestMatchingSubstring(string1, string2);
Console.WriteLine(longest);
}
static string FindLongestMatchingSubstring(string lhs, string rhs)
{
var left = lhs.AsMemory();
var right = rhs.AsMemory();
ReadOnlyMemory<char> longest = ReadOnlyMemory<char>.Empty;
for (int i = 0; i < left.Length; ++i)
{
foreach (var block in FindMatchingSubSpans(left, i, right))
{
if (block.Length > longest.Length)
longest = block;
}
}
if (longest.IsEmpty)
return string.Empty;
return longest.ToString();
}
static IEnumerable<ReadOnlyMemory<char>> FindMatchingSubSpans(ReadOnlyMemory<char> source, int pos, ReadOnlyMemory<char> matchFrom)
{
int lastMatch = 0;
for (int i = pos; i < source.Length; ++i)
{
var ch = source.Span[i];
int match = IndexOfChar(matchFrom, lastMatch, ch);
if (-1 != match)
{
lastMatch = match + 1;
int end = i;
while (++end < source.Length && ++match < matchFrom.Length)
{
char lhs = source.Span[end];
char rhs = matchFrom.Span[match];
if (lhs != rhs && lhs != (char.IsUpper(rhs) ? char.ToLower(rhs) : char.ToUpper(rhs)))
{
break;
}
}
yield return source.Slice(i, end - i);
}
}
}
static int IndexOfChar(ReadOnlyMemory<char> source, int pos, char ch)
{
char alt = char.IsUpper(ch) ? char.ToLower(ch) : char.ToUpper(ch);
for (int i = pos; i < source.Length; ++i)
{
char m = source.Span[i];
if (m == ch || m == alt)
return i;
}
return -1;
}
Okay, I know that this code is crude, and all around a messy, but I am no programmer, so bear with me. I have this code that lists a bunch of numbers, but I want it to not list any circular copies of the numbers.
For example, if the number 111262 is on my list, I don't want 112621, 126211, 262111, 621112, or 211126 to be listed.
Sorry, that number cannot be on the list.
For a true example, if the number 111252 is on my list, I don't want 112521, 125211, 252111, 521112, or 211125 to be listed.
Any help is appreciated!
namespace Toric_Classes
{
class Program
{
static void Main(string[] args)
{
int number_of_perms=0;
bool badsubsum1;
bool badsubsum2;
int subsum1 = 0;
int subsum2 = 0;
int sum = 0;
int class_length=6;
int[] toric_class=new int[class_length];
// The nested for loops scroll through every possible number of length class_length, where each digit can have a value of 1,2,..., or class_length-1
// Each number is looked at as an array, and is not stored anywhere, only printed if it satisfies certain conditions
for(int i1=1; i1<class_length; i1++)
{
toric_class[0] = i1;
for (int i2 = 1; i2 < class_length; i2++)
{
toric_class[1] = i2;
for (int i3 = 1; i3 < class_length; i3++)
{
toric_class[2] = i3;
for (int i4 = 1; i4 < class_length; i4++)
{
toric_class[3] = i4;
for (int i5 = 1; i5 < class_length; i5++)
{
toric_class[4] = i5;
for (int i6 = 1; i6 < class_length; i6++)
{
badsubsum1 = false;
badsubsum2 = false;
toric_class[5] = i6;
// Find the value of the sum of the digits of our array.
// We only want numbers that have a total digit sum being a multiple of class_length
for (int k = 0; k < class_length; k++)
{
sum += toric_class[k];
}
// The follwong two nested loops find the value of every contiguous subsum of our number, but not the total subsum.
// We *do not* want any subsum to be a multiple of class_length.
// That is, if our number is, say, 121342, we want to find 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
// The following checks 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 1+3, 1+3+4, and 3+4
for (int i = 0; i < class_length - 1; i++)
{
for (int j = i + 1; j < class_length - 1; j++)
{
for (int k = i; k < j; k++)
{
subsum1 += toric_class[k];
}
if (subsum1 % class_length == 0)
{
badsubsum1 = true;
break;
}
subsum1 = 0;
}
}
// The following checks 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
for (int i = 1; i < class_length; i++)
{
for (int j = i + 1; j < class_length; j++)
{
for (int k = i; k < j; k++)
{
subsum2 += toric_class[k];
}
if (subsum2 % class_length == 0)
{
badsubsum2 = true;
break;
}
subsum2 = 0;
}
}
// We only want numbers that satisfies the following conditions
if (sum % class_length == 0 && badsubsum1 == false && badsubsum2 == false)
{
foreach (var item in toric_class)
{
Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
number_of_perms++;
}
sum = 0;
subsum1 = 0;
subsum2 = 0;
}
}
}
}
}
}
Console.WriteLine("Number of Permuatations: "+number_of_perms);
Console.Read();
}
}
}
EDIT
To clarify, I am creating a list of all numbers with length n that satisfy certain conditions. Consider the number d1d2...dn, where each di is a digit of our number. Each di may have value 1,2,...,n. Our number is in the list if it satisfies the following
The sum of all the digits is a multiple of n, that is,
d1+d2+...+dn = 0 mod n
Every contiguous subsum of the digits is not a multiple of n, aside from the total sum, that is, if i !=1 and j != n, then
di+d(i+1)+...+dj != 0 mod n
I should mention again that a "number" does not strictly use the numbers 0-9 in its digits. It may take any value between 1 and n. In my code, I am using the case where n=6.
The code works by creating an array of length class_length (in the code above, I use class_length=6). We first have 6 nested for loops that simply assign values to the array toric_class. The first for assigns toric_class[0], the second for assigns toric_class[1], and so on. In the first go around, we are generating the array 111111, then 111112, up to 111115, then 111121, etc. So essentially, we are looking at all heximal numbers that do not include 0. Once we reach our sixth value in our array, we check the array toric_class and check its values to ensure that it satisfies the above conditions. If it does, we simply print the array in a line, and move on.
Here is my easy and inefficient way that should work with minimal changes to your code. It requires shared string list var strList = new List<string>(); to store the used numbers. Then this part:
foreach (var item in toric_class)
{
Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
number_of_perms++;
becomes something like this:
string strItem = " " + string.Join(" ", toric_class) + " "; // Example: int[] {1, 12, 123} becomes " 1 12 123 "
if (!strList.Any(str => str.Contains(strItem))) // Example: if " 1 12 123 1 12 123 " contains " 1 12 123 "
{
Console.WriteLine(strItem);
strItem += strItem.Substring(1); // double the string, but keep only one space between them
strList.Add(strItem);
}
number_of_perms++; // not sure if this should be in the if statement
The idea is that for example the string " 1 1 1 2 5 2 1 1 1 2 5 2 " contains all circular copies of the numbers {1, 1, 1, 2, 5, 2}. I used string as a lazy way to check if array contains sub-array, but you can use similar approach to store copy of the used numbers in a list of arrays new List<int[]>() and check if any of the arrays in the list is circular copy of the current array, or even better HashSet<int[]>() approach similar to #slavanap's answer.
The first version of my answer was the easiest, but it works only with array of single digit items.
List is almost the same as array (new List<string>() instead of new string[]), but makes it much easier and efficient to add items to it. For example {1,2}.Add(3) becomes {1,2,3}.
str => str.Contains(strItem) is shortcut for a function that accepts parameter str and returns the result of str.Contains(strItem). That "function" is then passed to the .Any LINQ extension, so
strList.Any(str => str.Contains(strItem))
is shortcut for something like this:
foreach(string str in strList)
{
if (str.Contains(strItem))
{
return true;
}
}
return false;
The following method:
private static List<int> GetCircularEquivalents(int value)
{
var circularList = new List<int>();
var valueString = value.ToString();
var length = valueString.Length - 1;
for (var i = 0; i < length; i++)
{
valueString = valueString.Substring(1, length) + valueString.Substring(0, 1);
circularList.Add(int.Parse(valueString));
}
return circularList;
}
will return a list of the circular numbers derived from the input value. Using your example, this method can be called like this:
var circularList = GetCircularEquivalents(111262);
var dirtyList = new List<int> { 1, 112621, 2, 126211, 3, 262111, 4, 621112, 5, 211126, 6 };
var cleanList = dirtyList.Except(circularList).ToList();
which would result in a cleanList made up of the numbers 1 through 6, i.e. the dirtyList with all the circular numbers derived from 111262 removed.
That's where OOP really benefits. Comments inlined.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3 {
struct MyInt : IEquatable<MyInt> {
private int _value;
public MyInt(int value) {
_value = value;
}
// make it look like int
static public implicit operator MyInt(int value) {
return new MyInt(value);
}
public static explicit operator int(MyInt instance) {
return instance._value;
}
// main difference in these 3 methods
private int GetDigitsNum() {
int temp, res;
for (res = 0, temp = Math.Abs(_value); temp > 0; ++res, temp /= 10);
return res;
}
public bool Equals(MyInt other) {
int digits = other.GetDigitsNum();
if (digits != this.GetDigitsNum())
return false;
int temp = other._value;
// prepare mul used in shifts
int mul = 1;
for (int i = 0; i < digits - 1; ++i)
mul *= 10;
// compare
for (int i = 0; i < digits; ++i) {
if (temp == _value)
return true;
// ROR
int t = temp % 10;
temp = temp / 10 + t * mul;
}
return false;
}
public override int GetHashCode() {
// hash code must be equal for "equal" items,
// that's why use a sum of digits.
int sum = 0;
for (int temp = _value; temp > 0; temp /= 10)
sum += temp % 10;
return sum;
}
// be consistent
public override bool Equals(object obj) {
return (obj is MyInt) ? Equals((MyInt)obj) : false;
}
public override string ToString() {
return _value.ToString();
}
}
class Program {
static void Main(string[] args) {
List<MyInt> list = new List<MyInt> { 112621, 126211, 262111, 621112, 211126 };
// make a set of unique items from list
HashSet<MyInt> set = new HashSet<MyInt>(list);
// print that set
foreach(int item in set)
Console.WriteLine(item);
}
}
}
Output:
112621
I am developing a program in visual c# windows form application.
I need to find out the number of characters in a text box and display each characters' frequency in a list box. I have the following code:
private void btnCheckFrequency_Click(object sender, EventArgs e)
{
lstFreqMeter.Items.Clear();
string str;
int c = 1;
int strlen;
str = txtString.Text;
strlen = txtString.TextLength;
int[] counter = new int[strlen];
for (int i = 0; i < strlen; i++)
{
for (int j = i + 1; j < strlen; j++)
{
if (str[i] == str[j])
{
c += 1;
}
}
counter[i] = c;
c = 1;
}
for (int k = 0; k < counter.Length; k++)
{
lstFreqMeter.Items.Add(counter[k]);
}
}
In this code when I click the "Check Frequency" button the program gives, as output, the frequency of each character and repeated characters, and also spaces which we do not want.
3 loops to accomplish this is where you are going wrong. I think you are trying to make it too complicated.
Its frowned upon to give answers to homework questions, but some hints as to direction should help.
Declare a Dictionary<char, int>
Make only one loop. For each char in your string.
Inside the loop, populate a Dictionary<char, int> with your results.
If the char exists in the dictionary, set the int to int++, if not, add the char to the dictionary with int of 1.
Outside the loop, AddRange to your lstFreqMeter.Items.
You can get the number of chars in a string by using Count on the string.
Getting the frequency of each char you can iterate through the string and increment an integer. A dictionary (key/value list) would be a great datatype to hold this data.
const string textString = "aaabbbcccaaattteeevvvooo";
var numberOfChars = textString.Count();
var dictionary = new Dictionary<char,int>();
foreach (var letter in textString)
{
if (dictionary.ContainsKey(letter))
dictionary[letter]++;
else
dictionary[letter] = 1;
}
The Dictionary will contain a key (the char) and a value (the count).
Try something like this:
var letters = Enumerable.Range('A', 26).Select(i => (char)i);
var sourceChars = letters.Concat(myString.ToUpperInvariant());
var results = from c in sourceChars
group c by c into g
where char.IsLetter(g.Key)
orderby g.Key
select new { Char = g.Key, Count = g.Count() - 1 };
foreach (var result in results)
{
Console.WriteLine("There are {0} {1}'s.", result.Count, result.Char);
}
This will return you a class of how many times each letter appears in myString
Maintain a dictionary of the matched characters and increment each character count as it is matched.
Dictionary<char, int> count = new Dictionary<char,int>();
string str = textString.Text;
int len = str.Length;
for(int i = 0; i < len; i ++)
{
if (str[i] == ' ') continue;
if (count.ContainsKey(str[i]))
{
count[str[i]] += 1;
} else {
count.Add(str[i], 1);
}
}
foreach(char key in count.Keys)
{
Console.WriteLine("{0} : {1}", key, count[key]);
}
I have many strings. Each string is prepended with at least 1 $. What is the best way to loop through the chars of each string to count how many $'s there are per string.
eg:
"$hello" - 1
"$$hello" - 2
"$$h$ello" - 2
You could use the Count method
var count = mystring.Count(x => x == '$')
int count = myString.TakeWhile(c => c == '$').Count();
And without LINQ
int count = 0;
while(count < myString.Length && myString[count] == '$') count++;
The simplest approach would be to use LINQ:
var count = text.TakeWhile(c => c == '$').Count();
There are certainly more efficient approaches, but that's probably the simplest.
You could do this, it doesn't require LINQ, but it's not the best way to do it(since you make split the whole string and put it in an array and just pick the length of it, you could better just do a while loop and check every character), but it works.
int count = test.Split('$').Length - 1;
var str ="hello";
str.Where(c => c == 'l').Count() // 2
int count = yourText.Length - yourText.TrimStart('$').Length;
int count = Regex.Matches(myString,"$").Count;
public static int GetHowManyTimeOccurenceCharInString(string text, char c)
{
int count = 0;
foreach(char ch in text)
{
if(ch.Equals(c))
{
count++;
}
}
return count;
}
just a simple answer:
public static int CountChars(string myString, char myChar)
{
int count = 0;
for (int i = 0; i < myString.Length; i++)
{
if (myString[i] == myChar) ++count;
}
return count;
}
Cheers! - Rick
One approach you could take is the following method:
// Counts how many of a certain character occurs in the given string
public static int CharCountInString(char chr, string str)
{
return str.Split(chr).Length-1;
}
As per the parameters this method returns the count of a specific character within a specific string.
This method works by splitting the string into an array by the specified character and then returning the length of that array -1.
//This code worked for me
class CountOfLettersOfString
{
static void Main()
{
Console.WriteLine("Enter string to check count of letters");
string name = Console.ReadLine();
//Method1
char[] testedalphabets = new char[26];
int[] letterCount = new int[26];
int countTestesd = 0;
Console.WriteLine($"Given String is:{name}");
for (int i = 0; i < name.Length - 1; i++)
{
int countChar = 1;
bool isCharTested = false;
for (int j = 0; j < testedalphabets.Length - 1; j++)
{
if (name[i] == testedalphabets[j])
{
isCharTested = true;
break;
}
}
if (!isCharTested)
{
testedalphabets[countTestesd] = name[i];
for (int k = i + 1; k < name.Length - 1; k++)
{
if (name[i] == name[k])
{
countChar++;
}
}
letterCount[countTestesd] = countChar;
countTestesd++;
}
else
{
continue;
}
}
for (int i = 0; i < testedalphabets.Length - 1; i++)
{
if (!char.IsLetter(testedalphabets[i]))
{
continue;
}
Console.WriteLine($"{testedalphabets[i]}-{letterCount[i]}");
}
//Method2
var g = from c in name.ToLower().ToCharArray() // make sure that L and l are the same eg
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in g)
{
Console.WriteLine(string.Format("Character:{0} Appears {1} times", item.Key.ToString(), item.Count));
}
Console.ReadLine();
}
}
This is a similar Solution to find how many email addresses included in a string. This way is more efficient`
int count = 0;
foreach (char c in email.Trim())
if (c == '#') count++;
I`m trying to create a special counter in C# ... I mean the counter will be consisting of characters not numbers.
I have a char[] of size 3:
char[] str = new char[strSize];
int i = 0;
int tmpSize = strSize - 1;
int curr;
while(!isEqual(str,finalStr,strSize))
{
str[strSize] = element[i % element.Length];
i++;
if (str[strSize] == element[element.Length - 1])
{
int j = strSize - 1;
if (j > 0)
{
j--;
int tmpCntr = j+1;
curr = getCurrentID(str[tmpCntr]);
str[tmpCntr] = element[(curr + 1) % element.Length];
while (str[tmpCntr] == element[0] && (i % element.Length > 0) && tmpCntr < 0)
{
tmpCntr--;
curr = getCurrentID(str[tmpCntr]);
str[tmpCntr] = element[(curr + 1) % element.Length];
}
}
}
}
if the strSize < 3 the application works fine and gives accurate output. If the strSize >= 3, the application goes in infinite loop!
Need help.
if this is hard this way, I would need a way to create a numerical counter and I`ll work on it to suite my application.
You haven't shown what half of your methods or parameters are.
Personally I would take a different approach. I would use an iterator block to make it easy to return an IEnumerable<string>, and internally just keep an integer counter. Then you just need to write a method to convert a counter value and "alphabet of digits" into a string. Something like this:
public static IEnumerable<string> Counter(string digits, int digitCount)
{
long max = (long) Math.Pow(digits.Length, digitCount);
for (long i = 0; i < max; i++)
{
yield return ConvertToString(i, digits, digitCount);
}
}
Another alternative is to do the same thing with LINQ, if a range of int is enough:
public static IEnumerable<string> Counter(string digits, int digitCount)
{
int max = (int) Math.Pow(digits.Length, digitCount);
return Enumerable.Range(0, max)
.Select(i => ConvertToString(i, digits, digitCount));
}
In either case, you just iterate over the returned sequence to get appropriate counter values.
With those in place, you just need to implement ConvertToString - which would probably be something like this:
public static string ConvertToString(long value, string digits, int digitCount)
{
char[] chars = new char[digitCount];
for (int i = digitCount - 1 ; i >= 0; i--)
{
chars[i] = digits[(int)(value % digits.Length)];
value = value / digits.Length;
}
return new string(chars);
}
Here's a test program showing it all working:
using System;
using System.Collections.Generic;
using System.Linq;
class Test
{
static void Main()
{
// Show the first 10 values
foreach (string value in Counter("ABCD", 3).Take(10))
{
Console.WriteLine(value);
}
}
public static IEnumerable<string> Counter(string digits, int digitCount)
{
long max = (long) Math.Pow(digits.Length, digitCount);
for (long i = 0; i < max; i++)
{
yield return ConvertToString(i, digits, digitCount);
}
}
public static string ConvertToString(long value,
string digits,
int digitCount)
{
char[] chars = new char[digitCount];
for (int i = digitCount - 1 ; i >= 0; i--)
{
chars[i] = digits[(int)(value % digits.Length)];
value = value / digits.Length;
}
return new string(chars);
}
}
Output:
AAA
AAB
AAC
AAD
ABA
ABB
ABC
ABD
ACA
ACB