I'm working on an windows app. This app contains a dynamic list of names, that are displayed in the form (user can add or delete a certain name). What I want to do is for each name in db have another random name from the list. The only condition is that for each name should be asssigned different name and all the names must be used only once.
What I've tried to do is using a List to contain names from db and pick a random index from the List and compare it with the corresponding place in db. If it's different then remove at that index, and so on until no more names to place.
But after that I realised it's not a perfect way to do it. Let's say, I've got 5 names,
name 1 randomly gets name 3 name 2 randomly gets name 1 name 3 randomly gets name 4 name 4 randomly gets name 2 and... name 5 can only get name 5, so in this case it doesn't开发者_运维问答 work.
Anyone has any idea how I could make it work? What other method should I use? Number of names is about 20. Later on I will have to assign 2 different names for each name. But at first I need to solve this problem.
Any help will be appreciated! I'm writing in C#
Jan beat me to it, but here's the code I was doing to explain how you just need to switch the two last if the non-selected names match.
static void Main(string[] args)
{
List<string> names = new List<string>() { "Jeff", "John", "Joe", "Jack", "Jim" };
List<string> otherNames = new List<string>() { "Jeff", "John", "Joe", "Jack", "Jim" };
Random r = new Random();
for (int i = 4; i >= 0; i--)
{
int pick1 = r.Next(i);
int pick2 = r.Next(i);
while (names[pick1] == otherNames[pick2])
{
pick2++;
if (pick2 >= otherNames.Count) pick2 = 0;
}
if (names.Count == 2)
{
// when you only have 2 names left, if the other names match...
if (names[1 - pick1] == otherNames[1 - pick2])
{
// swap one of the picked names
pick2 = 1 - pick2;
}
}
Console.Write(names[pick1]); Console.Write(" != "); Console.WriteLine(otherNames[pick2]);
names.RemoveAt(pick1);
otherNames.RemoveAt(pick2);
}
Console.ReadKey();
}
Use the method you propose and Just swap the last two elements when you encounter the problem you described.
while (position == 0) {
position = randInt() % nameCount;
}
for (int i=0;i<nameCount;i++) {
addPair(i,position);
position++;
if (position>=nameCount) position=0;
}
Names in db are logically numbered from 0 to nameCount-1; The idea is that you choose random position for the second name and then increment it and roll over at the end.
This is pseudocode. I don't know C#.
Great question!
You might want to look at this similar problem or the answers to ruby quiz 2 for ideas.
A basic approach might be to copy the list, shuffle the copy and line the two up. But that can end up with the same issue you have. But then look through the list you can swap with each self-referencing one.
I think it would just be simpler to shuffle one List<string> names
, create a copy, shift the copy one item down (make last item become first) and match names by position. You ensure no duplicates in one pass.
精彩评论