I need to get help with replacing repeating numbers in each line printed out. If a line prints out for example: "41 25 1 41 3 7" how do I replace one of the 41's for another number?
using System;
class Program
{
static void Main()
{
Draw();
Console.ReadKey();
}
static void Draw()
{
int choice;
Random randomNum = new Random();
int[] numbers = new int[6];
Console.Write("enter line amount: ");
choice = int.Parse(Console.ReadLine());
for (int i = 0; i < choice; i )
{
Console.Write("\n");
for (int j = 0; j < numbers.Length; j )
{
numbers[j] = randomNum.Next(1, 49);
Console.Write("{0} ", numbers[j]);
}
}
}
}
CodePudding user response:
The shuffle suggestion from the comments is mostly the correct approach here. Generally, you start with the full set, and then shuffle the set and take the first n
shuffled values. However, we can improve on that; since we only need a few numbers we can bail on the shuffle early. So we have this answer, based on adapting a Fisher-Yates shuffle to only do as much as needed:
class Program
{
static Random rand = new Random();
static IEnumerable<int> generateSet(int max, int count)
{
var corpus = Enumerable.Range(1, max).ToArray();
for (int i = 0; i < count; i )
{
var nextIndex = rand.Next(i, max);
yield return corpus[nextIndex];
corpus[nextIndex] = corpus[i];
}
}
static void Main()
{
Console.Write("enter line amount: ");
int choice = int.Parse(Console.ReadLine());
var result = generateSet(49, choice);
Console.WriteLine(string.Join(" ", result));
Console.ReadKey(true);
}
}
See it here:
Note how this removes any interaction with the user from the part that does the work. It's better structure to separate those concerns. Also note how this moves the Random
instance up to the class, instead of the method. Random
works much better when you re-use the same instance over time.
The exception to this is when the set is truly large or unbounded. Then you need a different algorithm that checks every generated random value against the ones that came before, and tries again while (that word was a hint) it finds a collision. However, it's worth noting this is usually slower on average. Checking prior numbers works out to O(n log n)
, while generate shuffle is only O(n)
. But if the value of n
is unknown or truly large (many thousands), while the number of random items is small, it can be more effective.
CodePudding user response:
You can avoid repeating numbers using a do/while
loop that generates new numbers until it found one that has not been drawn yet.
I also applied some refactorings, hope you like it:
class Program
{
static void Main()
{
new Program().Draw();
Console.ReadKey();
}
Random randomNum = new Random();
void PrintLine()
{
int[] numbers = new int[6]; // maybe change that to List<int>
for (int j = 0; j < numbers.Length; j )
{
int number;
do // <--major change is here
{
number = randomNum.Next(1, 49);
} while (numbers.Contains(number));
numbers[j] = number;
Console.Write("{0} ", number);
}
}
void Draw()
{
Console.Write("enter line amount: ");
int choice = int.Parse(Console.ReadLine());
for (int i = 0; i < choice; i )
{
Console.WriteLine(); // instead of Write("\n")
PrintLine();
}
}
}
Note that it might run into an endless loop if you're trying to generate more numbers than available.
CodePudding user response:
There is a way to do without a shuffle, by simply jumping a pointer "randomly" inside a stack or array, and off course deleting or resetting the currently used value (at 0 lets say or flip sign) then make a check after next jump to be sure not being on a reset address. It could be easier to implement than the shuffle if you use assembly or have perf/ram constraint to a shuffle or past picked value check approach since the algorithmic price is linear with size, or if you need to choose from a premade/imported list of item which kinda is with your approach since generated values are finite and definite.
There are also issues with the randomness or the standard random function (in nearly every language), either for fairness, predictability, performance, portability or simply the option to repeat a result (same seed). If any of the above is a live or death issue for you, consider an alternative to random class, either from ext lib, written yourself or the slightly better crypto : How do I generate a random integer in C#?
Oh and don't forget, have fun!