1

I am writing a program where I need to shuffle a list of persons and link them to another person from the list. But the problem is with odd numbers, because 1 person can be linked to themself. (I made that impossible so then nothing happens.)

For example, if there are 3 persons called 'Bill', 'John' and 'Jonas'. If 'Bill' gets 'Jonas' and 'Jonas' gets 'Bill', then 'John' is getting linked to 'John', but I made that impossible (to get themself) so nothing happens then.

Does anyone know how I can fix this?

cigien
  • 57,834
  • 11
  • 73
  • 112
Usus woa
  • 43
  • 6

2 Answers2

6

This is essentially a "secret santa" problem. There is a simple algorithm for this:

  1. Shuffle the list of people randomly.
  2. For each person (except the last), link them to the next person in the list.
  3. Link the last person to the first.

This is guaranteed to be a random linking, and guarantees that no person is linked to themself.

Note that this is not truly random, in that there are no sub-groups of people who are linked to each other. Starting from any person, you would be able to follow links and reach every other person. If I recall correctly, I think about a third of the time in a random linking there would be sub-groups that are not reachable from one another. However, this form of shuffling and linking should be adequate for your purposes.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • This is normally adequate but note that it discounts a set of possibilities - e.g. two closed loops. – Bathsheba Aug 18 '20 at 21:08
  • @Bathsheba True, but from OP's description I doubt they need that. – cigien Aug 18 '20 at 21:11
  • It might be worth mentioning though in the answer, just in case. E.g. if you had a random number generator that only generated a certain class of number, then you'd feel compelled to point it out. (Nice answer though, +1). – Bathsheba Aug 18 '20 at 21:12
  • @cigien I never knew that you could shuffle lists. This is an easy way to do it, thanks. – Usus woa Aug 18 '20 at 21:14
  • @Bathsheba Good point, added the caveat. I'm doing this from a faint memory of stuff I read a long time ago, so please feel free to edit the post if I made a mistake. – cigien Aug 18 '20 at 21:17
  • For multiple cycles simply split the list explained in the above answer into random number of lists of maximum splits of (r/2)-1. Simply find a split by dividing the list at into random length "halfs" until the random number of splits is reached. Note that no split can leave a person on their own, so a split can only be made if both sub lists at either side of the split are 2 or more big. This should always be possible as you have at most (r/2)-1 splits to make. Note that you may have to move splits around to ensure that each person has 1+ "partners". It is a difficult algorithm to explain. – ceorron Aug 18 '20 at 21:43
  • @ceorron: My feeling is you'll introduce statistical bias into medium sized groups being formed preferentially. There's probably a PhD on this out there somewhere. – Bathsheba Aug 19 '20 at 06:28
  • Probably does introduce some bias, given that all split's must be at least 2 big, meaning some splits cannot happen, meaning some splits are more likely, for example if there are three together like the original poster had it. Meaning those next to each other in the original list are more likely to be in the same group in the end. Actually because it is completely random ordering. I think this would completely negate this as it is still random who is next to who meaning we can modify the splits to each be 2 or bigger without introducing any bias. – ceorron Aug 19 '20 at 09:27
2

Put people in random order, e.g. by using shuffle and then assign person i to person i+1 and last one to first one. Nobody will get itself.

Łukasz Ślusarczyk
  • 1,775
  • 11
  • 20