-2

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]);
            
        }


    }
 
   }
}
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
Martin
  • 9
  • 4
  • Think of what you need to begin with. You need a system that remembers the numbers being generated randomly before the current one. If the prior ones contains the newly generated one, don't make it write. – Soner from The Ottoman Empire Oct 11 '22 at 18:39
  • 2
    Why do you want to replace repeating numbers? Couldn't you avoid creating duplicates in the first place? – Thomas Weller Oct 11 '22 at 18:40
  • If numbers[1] = 41 {numbers[1] = 6;} Not clear this question – Tony Hopkinson Oct 11 '22 at 18:40
  • Why not create a list/array of all numbers from 1-48, *shuffle* them (you may need to research that), then take 6 of them (research: LINQ's `Take`)? Six numbers in the desired range with no repeats...not much to do with random. – Ňɏssa Pøngjǣrdenlarp Oct 11 '22 at 18:48
  • Is this for generating lotto 6 49 numbers? Consider making an array of the numbers 1-49, then randomly _shuffling_ 6 of them to the front of the array with a [_knuth shuffle_](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle). Be aware that [Random.Next](https://learn.microsoft.com/en-us/dotnet/api/system.random.next?view=net-6.0#system-random-next(system-int32-system-int32)) uses 49 as an **exclusive** upper bound (but lotto 6 49 *includes* the number 49) – Wyck Oct 11 '22 at 19:36

3 Answers3

1

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:

https://dotnetfiddle.net/aiJnS2

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.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
0

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.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
0

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!

Edit: Also I would recommend to read the comments of a recent dailyWTF on similar problem; all approaches are intelligently discussed: https://thedailywtf.com/articles/top-slots

Patrick
  • 1
  • 2