Reputation: 1335
I'm working on a .NET application in C# that will generate a variable-length string of random digits. I'd like to add a checklist that will allow the user to select any combination of digits between zero and nine and prevent them from appearing in the string. Currently, I simply do this to get the string:
do
{
int num = rnd.Next(10);
output += num.ToString();
i++;
}
while (i < stringLength);
I can think of a way to exclude selected digits by throwing them out once they are generated and not incrementing the counter, but it seems like there would be a less wasteful algorithm. The program will support generating a number of strings, so if a user is creating millions of strings, I'd like to keep overhead at a minimum.
Bonus: I forgot to mention that I'd also like if someone could point me to a resource for patterns such as this. I'll be working a lot with random numbers based on parameters in the near future and I'd like to learn some principles instead of asking questions about individual problems such as this.
Upvotes: 1
Views: 4537
Reputation: 137148
If you generate an array of allowed characters then pick from that:
int[] allowedDigits = {1, 2, 3, 6, 7, 0};
var output = new StringBuilder();
do
{
int num = rnd.Next(allowedDigits.Length);
output.Append(allowedDigits[num]);
i++;
}
while (i < stringLength);
obviously allowedDigits
is generated rather than hard coded ;)
Using a StringBuilder
is more efficient and you don't have to explicitly do the ToString
.
Upvotes: 15
Reputation: 4433
Just for a laugh, here's a gratuitously "clever-clever" way of doing it:
int allowedDigits = {1, 3, 5, 4, 9};
//Generate an infinite sequence of numbers,
//so be careful not to do foreach over it!
IEnumerable<int> GenerateNumbers(int max)
{
while(true)
{
yield return rnd.Next(max);
}
}
var filteredNumbers = from num in GenerateNumbers(10)
where num in allowedDigits
select num;
output = String.Join("", fitleredNumbers.Take(stringLength));
(or words to that effect, no compiler to check it with at the mo...)
It goes without saying that this is probably hopelessly inefficient...
Upvotes: 0
Reputation: 15344
int [] excludeNum={2 , 3 , 4};
do
{
int num = rnd.Next(10);
if(excludeNum.Contains(num))
continue;
output += num.ToString();
i++;
}
while (i < stringLength);
By using continue
statement you can change flow of control back to while();
without incrementing i
;
Upvotes: 0
Reputation: 6891
string[] num = new string[9];
int j = 0;
for(int k = 0; k < num.length; k++)
if (k != numToExclude)
num[j++] = k.ToString();
}
StringBuilder output = new StringBuilder(stringLength);
do
{
int n = rnd.Next(10);
output.Append(num[n]);
i++;
}
while (i < stringLength);
In the code above, you may change the num
data type char
. Not sure if that optimizes anything.
Upvotes: 0
Reputation: 10974
Upvotes: 4