Pairing People for Weekly Dates

41 Views Asked by At

I'm trying to make a program to create pairs of people to have 1:1 chats with each other weekly. A person will not pair up with someone they've paired before (eg. [A,B] in Week 1, so [A,B] or [B,A] will not appear again in Week 2), there are no duplicates (eg. [A,B] is the same as [B,A]), and a person can't be in two pairs for one week (eg. [A, B] meets in Week 1, so [A, C] cannot meet in Week 1 because A is already in a pair).

It takes in an array of people that are strings and pair each person up with someone else in the array. I also have a dates array with numbers from 1 to n. You can imagine element 1 being Week 1, element 2 being Week 2, and so on.

So for example:


Input: string[] people = ["John", "David", "Mary", "Susan"] and int[] dates = [1,2,3]

Output: [(Week 1, "John", "David"), (Week 1, "Mary", "Susan"), (Week 2, "John", "Mary"), (Week 2, "David", "Susan"), (Week 3, "John", "Susan"), (Week 3, "David", "Mary")]

The format of the output doesn't matter, it can be an array of tuples, array of lists, etc. It just needs to somehow communicate the week and the pair.

What I've Tried

I'm new to C# and I've been trying to solve this using Linq/MoreLinq and HashSets, but to no avail. I created all the different combinations with this:

var x = people
            .SelectMany(g => people
            .Select(c => new Tuple<string, string> (g, c)))
            .Where(x => x.Item1 != x.Item2).ToList() // To remove pairs where a person matches with itself
            .SelectMany(g => dates
            .Select(c => new Tuple<string, string, int>(g.Item1, g.Item2, c)))
            .OrderBy(x => x.Item3)
            .ToList();

and then tried to filter out the ones that are not valid using a HashSet. The Tuple contains (Item1 = person1, Item2 = person2, Item3 = date).

HashSet<Tuple<string, string>> previouslySelected = new HashSet<Tuple<string, string>>();
List<Tuple<string, string, int>> RemoveList2 = new List<Tuple<string, string, int>>(x);

foreach(var item in RemoveList2)
{
   if(previouslySelected.Contains(new Tuple<string, string>(item.Item1, item.Item2)) // Remove duplicates
   || previouslySelected.Contains(new Tuple<string, string>(item.Item2, item.Item1)) // Remove the inverse
   || previouslySelected.Contains(new Tuple<string, string>(item.Item1, item.Item3.ToString())) // Remove the rest of the pairs that have people that are already paired up for that week
   || previouslySelected.Contains(new Tuple<string, string>(item.Item2, item.Item3.ToString())))
   {
      x.Remove(item);
   } else
     {
       previouslySelected.Add(new Tuple<string, string>(item.Item1, item.Item2));
       previouslySelected.Add(new Tuple<string, string>(item.Item2, item.Item3.ToString()));
       previouslySelected.Add(new Tuple<string, string>(item.Item1, item.Item3.ToString()));
      }
   }

Yes, this is probably a very roundabout way to do this, but I'm not sure how to go about this and this implementation doesn't work either. I get:

(John, Jack, 1)
(David, Jesse, 1)
(Mary, Sally, 1)
(Lisa, Kevin, 1)
(Sue, Hansel, 1)
(Jen, Rachel, 1)

(John, David, 2)
(Jack, Jesse, 2)
(Mary, Lisa, 2)
(Sally, Kevin, 2)
(Sue, Jen, 2)
(Hansel, Rachel, 2)

(John, Jesse, 3)
(Jack, David, 3)
(Mary, Kevin, 3)
(Sally, Lisa, 3)
(Sue, Rachel, 3)
(Hansel, Jen, 3)

(John, Mary, 4)
(Jack, Sally, 4)
(David, Lisa, 4)
(Jesse, Kevin, 4)

Everything seems fine until we get to the 4th week. We should be seeing 6 pairs for each week (my array has 12 people). Did some digging and it seems like it got stuck because the leftover pairs were not valid and got removed.

Any help is appreciated.

Edit

I was making my life so much harder. I just used the round robin algorithm

0

There are 0 best solutions below