0

I have a arraylist of names which get added 1 by 1. The range of the random number is the amount of people inside the arraylist.

For example: NameList => [James, Vince, Joe, Joseph, John]

I want the output to be

NameListNum => [James 3, Vince 2, Joe 5, Joseph 1, John 4]

or

NameListNum => [James 2, Vince 5, Joe 1, Joseph 4, John 3]\

        foreach (var name in nameList)
        {
            counter++;
            int randomNum = rand.Next(Decimal.ToInt32(numOfShooters))+1;
            nameListNum.Add(name + " "+randomNum);
            foreach (var item in nameListNum)
            {

            }
        }

Don't know if I am going in the right direction but the second foreach loop would be the one that checks the other nameListNum strings and regenerate a random number and rewrite it to the name.

Carlos
  • 5,991
  • 6
  • 43
  • 82
  • 1
    and what is your problem? There are plenty of similar questions, just **search and try**. E.g. "shuffle list" – MakePeaceGreatAgain Aug 11 '20 at 08:48
  • each one i find is more complicated than should be and not applicable to my needs, i need for the random number generated to be different. – Alvin Cassar Aug 11 '20 at 08:52
  • please show what you´ve tried already. Otherwise chances are someone provides an answer you´ve already tried out yourself. It doubt that´ll help you, so please provide more information about what you´ve tried and where exactly you have difficulties. – MakePeaceGreatAgain Aug 11 '20 at 08:54
  • added an edit to my question :) – Alvin Cassar Aug 11 '20 at 09:00
  • Surely you just need to remove a name form the list each time you select it, and lower the numOfShooters value accordingly? – ProgrammingLlama Aug 11 '20 at 09:20

2 Answers2

1

Given that it is very easy to find the code to Shuffle a list of generated numbers randomly, the code is as easy as

var namesList = new []{"James", "Vince", "Joe", "Joseph", "John"};
var numsList = Enumerable.Range(1,namesList.Length).ToList().Shuffle();
var namesNumsList = namesList.Select( (n,i) => $"{n} {numsList[i]}").ToList();

Live example: https://dotnetfiddle.net/MzOwQa

If you want to randomise the names make them a List<string>:

var namesList = new List<string>{"James", "Vince", "Joe", "Joseph", "John"}.Shuffle();

The only other change is that you'll need namesList.Count on the following line in place of namesList.Length

Jamiec
  • 133,658
  • 13
  • 134
  • 193
1

Ok, let's go step by step. You have a list of names and you want to assign a unique random number to each name. The random numbers must be within the range [1, number of names in the list]

The naive brute force way would be to generate a random number, check if it has been rolled before and if not assign it to a name. Repeat the process for each name in the list in order and you are done.

With 4 or 5 names, this will actually run pretty fast but its wateful. Even more when lists get very big, getting to the point where its wasteful and performs horribly. Why? Well you need to roll many more times than necessary.

Is there a better way? Yes. Imagine you problem is: write a method that returns one by one random cards in a standard deck? Would you do it the same way? Or would you somehow store and ordered deck, shuffle it and then simply hand the cards out one by one?

Well, here its the same. Your standard deck is simply an ordered list of numbers from 1 to the total number of shooters: 1, 2, 3, ...., numberOfShooters.

Now, how would you shuffle it. Well, a naive way would be to create a list, then randomly pick an index, pick the number stored in that list and then remove it from the list to avoid rolling it again. That would work, but again, its wasteful. Why? Because repeatedly removing items in a list can be expensive. Remember lists are just wrappers over a standar array; removing an item mid list entails that all following numbers must be shifted un position up in the array.

An easy way to shuffle a list without all these problems is to use linq (there are better ways but this should suffice in your case):

var numbersToShuffle = Enumerable.Range(1, numberOfShooters);
var rnd = new Random();
numbersShuffled = numbersToShuffle.OrderBy(i => rnd.Next());

The rest should be easy.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • Well, if you're going to explain it that way: for me the simplest thing that requires a *one by one update* is to stick in a card at a random location, and there are N+1 possible locations where N is the current size of the stack... – Maarten Bodewes Aug 11 '20 at 09:14
  • even more efficient: shuffle them in-place instead of generating a whole new enumerable object! – Jamiec Aug 11 '20 at 09:16
  • Thank you, was making my life hard as it seems – Alvin Cassar Aug 11 '20 at 09:19
  • @MaartenBodewes @ Jamiec Yes there are tons of ways to do this better. The whole point of this answer is to make him understand that starting from an ordered list and then shuffling it, nevermind how, is the way to go instead of generating random numbers on the go like he seems to be doing... form there on, if needed, he can optimize everything to make it as blindingly fast or memory efficient as he needs to... I'm not sure the use of explaining efficient sorting algorithms when the OP still doesn't know how to solve the problem. – InBetween Aug 11 '20 at 09:21