12

I work in a consulting organization and am most of the time at customer locations. Because of that I rarely meet my colleagues. To get to know each other better we are going to arrange a dinner party. There will be many small tables so people can have a chat. In order to talk to as many different people as possible during the party, everybody has to switch tables at some interval, say every hour.

How do I write a program that creates the table switching schedule? Just to give you some numbers; in this case there will be around 40 people and there can be at most 8 people at each table. But, the algorithm needs to be generic of course

Mike B
  • 12,768
  • 20
  • 83
  • 109
Hallis
  • 159
  • 1
  • 6
  • Does there have to be an equal number of male and female per table? – Unknown Jun 09 '09 at 07:56
  • No, i think the problem is hard enough as it is. – Hallis Jun 09 '09 at 08:18
  • 9
    Why don't you just create a Facebook group to keep in touch with each other? – Daniel Daranas Jun 09 '09 at 08:50
  • 1
    After reading the part of the Homework FAQ that states that the Homework tag shouldn't be added without proof of this being homework I've decided to remove the tag until the OP claims that this is a homework question (note: aren't most students on their summer holiday now?). Discuss. – Mike B Jun 10 '09 at 01:40
  • This is proven to be NP hard. The specific instance of "table size 2" and "I want everybody to meet everybody" is colloquially known as "the homosexual speed dating problem." There exists no optimal, fast, solution. – Jon Watte Jun 08 '19 at 00:22
  • @JonWatte the specific instance of "table size 2" and "I want everybody to meet everybody" is also known as "a round robin tournament". This is easily solved: https://en.wikipedia.org/wiki/Round-robin_tournament#Scheduling_algorithm. – Hugh W May 26 '20 at 11:42

9 Answers9

12

heres an idea
first work from the perspective of the first person .. lets call him X
X has to meet all the other people in the room, so we should divide the remaining people into n groups ( where n = #_of_people/capacity_per_table ) and make him sit with one of these groups per iteration
Now that X has been taken care of, we will consider the next person Y
WLOG Y be a person X had to sit with in the first iteration itself.. so we already know Y's table group for that time-frame.. we should then divide the remaining people into groups such that each group sits with Y for every consecutive iteration.. and for each iteration X's group and Y's group have no person in common
.. I guess, if you keep doing something like this, you will get an optimal solution (if one exists)

Alternatively you could crowd source the problem by giving each person a card where they could write down the names of all the people they got dine with.. and at the end of event, present some kind of prize to the person with the most names in their card

Aditya Mukherji
  • 9,099
  • 5
  • 43
  • 49
6

This sounds like an application for genetic algorithm:

  1. Select a random permutation of the 40 guests - this is one seating arrangement
  2. Repeat the random permutation N time (n is how many times you are to switch seats in the night)
  3. Combine the permutations together - this is the chromosome for one organism
  4. Repeat for how ever many organisms you want to breed in one generation
  5. The fitness score is the number of people each person got to see in one night (or alternatively - the inverse of the number of people they did not see)
  6. Breed, mutate and introduce new organisms using the normal method and repeat until you get a satisfactory answer

You can add in any other factors you like into the fitness, such as male/female ratio and so on without greatly changing the underlying method.

1800 INFORMATION
  • 131,367
  • 29
  • 160
  • 239
  • If I'm wrong, please point out why instead of the silent down-vote thing, thanks – 1800 INFORMATION Jun 09 '09 at 09:12
  • 2
    You shouldn't indiscriminately throw genetic algorithms at any optimization problem that comes along, in particular not at small and regular problems like this. – starblue Jun 09 '09 at 10:52
  • 2
    There are many good suggestions here, but I ended up implementing this as a genetic algorithm. Mainly because I hadn't done any GA's before and it sounded fun to do. You can download my code from here: http://hallvardkorsgaard.spaces.live.com/blog/cns!6A4336898CA0055D!407.entry – Hallis Jun 21 '09 at 18:58
6

Why not imitate real world?

class Person { 
    void doPeriodically() {
         do {
             newTable = random (numberOfTables);
         } while (tableBusy(newTable))
         switchTable (newTable) 
    }
}

Oh, and note that there is a similar algorithm for finding a mating partner and it's rumored to be effective for those 99% of people who don't spend all of their free time answering programming questions...

ilya n.
  • 18,398
  • 15
  • 71
  • 89
4

Perfect Table Plan

user79755
  • 2,623
  • 5
  • 30
  • 36
  • 1
    I am the author of PerfectTablePlan. PerfectTablePlan can handle this scenario, but it needs a bit of manual intervention: http://www.perfecttableplan.com/html/PerfectTablePlan_Windows_Help_402/index.html?arrange_multiple_seatings_for_an_event.htm It is on my 'wishlist' to extend PerfectTablePlan to handle multiple seatings better. – Andy Brice Jun 10 '09 at 08:45
  • @Andy Brice - Hehe, I just made the comment in jest. – user79755 Jun 10 '09 at 20:08
  • Update. PerfectTablePlan Professional edition v5 can handle the generation of multiple seatings in a single operation (using a genetic algorithm). It can also handle additional constraints, such as keeping couples together in all seatings or trying to sit A next to B for just 1 seating. See: http://www.perfecttableplan.com/help/52/windows/html/arrange_multiple_seatings_for_an_event.htm – Andy Brice Feb 19 '15 at 10:33
3

You might want to have a look at combinatorial design theory.

starblue
  • 55,348
  • 14
  • 97
  • 151
2

Intuitively I don't think you can do better than a perfect shuffle, but it's beyond my pre-coffee cognition to prove it.

user60401
  • 668
  • 1
  • 4
  • 6
2

This one was very funny! :D

I tried different method but the logic suggested by adi92 (card + prize) is the one that works better than any other I tried.

It works like this:

  1. a guy arrives and examines all the tables
  2. for each table with free seats he counts how many people he has to meet yet, then choose the one with more unknown people
  3. if two tables have an equal number of unknown people then the guy will choose the one with more free seats, so that there is more probability to meet more new people

at each turn the order of the people taking seats is random (this avoid possible infinite loops), this is a "demo" of the working algorithm in python:

import random

class Person(object):

    def __init__(self, name):
        self.name = name
        self.known_people = dict()

    def meets(self, a_guy, propagation = True):
        "self meets a_guy, and a_guy meets self"
        if a_guy not in self.known_people:
            self.known_people[a_guy] = 1
        else:
            self.known_people[a_guy] += 1

        if propagation: a_guy.meets(self, False)

    def points(self, table):
        "Calculates how many new guys self will meet at table"
        return len([p for p in table if p not in self.known_people])

    def chooses(self, tables, n_seats):
        "Calculate what is the best table to sit at, and return it"
        points = 0
        free_seats = 0
        ret = random.choice([t for t in tables if len(t)<n_seats])

        for table in tables:
            tmp_p = self.points(table)
            tmp_s = n_seats - len(table)
            if tmp_s == 0: continue
            if tmp_p > points or (tmp_p == points and tmp_s > free_seats):
                ret = table
                points = tmp_p
                free_seats = tmp_s

        return ret

    def __str__(self):
        return self.name
    def __repr__(self):
        return self.name


def Switcher(n_seats, people):
    """calculate how many tables and what switches you need
        assuming each table has n_seats seats"""

    n_people = len(people)
    n_tables = n_people/n_seats

    switches = []
    while not all(len(g.known_people) == n_people-1 for g in people):
        tables = [[] for t in xrange(n_tables)]

        random.shuffle(people) # need to change "starter"

        for the_guy in people:
            table = the_guy.chooses(tables, n_seats)
            tables.remove(table)
            for guy in table:
                the_guy.meets(guy)
            table += [the_guy]
            tables += [table]

        switches += [tables]

    return switches



lst_people = [Person('Hallis'),
      Person('adi92'),
      Person('ilya n.'),
      Person('m_oLogin'),
      Person('Andrea'),
      Person('1800 INFORMATION'),
      Person('starblue'),
      Person('regularfry')]    



s = Switcher(4, lst_people)

print "You need %d tables and %d turns" % (len(s[0]), len(s))
turn = 1
for tables in s:
    print 'Turn #%d' % turn
    turn += 1
    tbl = 1
    for table in tables:
        print '  Table #%d - '%tbl, table
        tbl += 1
    print '\n'

This will output something like:

You need 2 tables and 3 turns
Turn #1
  Table #1 -  [1800 INFORMATION, Hallis, m_oLogin, Andrea]
  Table #2 -  [adi92, starblue, ilya n., regularfry]


Turn #2
  Table #1 -  [regularfry, starblue, Hallis, m_oLogin]
  Table #2 -  [adi92, 1800 INFORMATION, Andrea, ilya n.]


Turn #3
  Table #1 -  [m_oLogin, Hallis, adi92, ilya n.]
  Table #2 -  [Andrea, regularfry, starblue, 1800 INFORMATION]

Because of the random it won't always come with the minimum number of switch, especially with larger sets of people. You should then run it a couple of times and get the result with less turns (so you do not stress all the people at the party :P ), and it is an easy thing to code :P

PS: Yes, you can save the prize money :P

Andrea Ambu
  • 38,188
  • 14
  • 54
  • 77
1

You can also take look at stable matching problem. The solution to this problem involves using max-flow algorithm. http://en.wikipedia.org/wiki/Stable_marriage_problem

user120015
  • 11
  • 1
1

I wouldn't bother with genetic algorithms. Instead, I would do the following, which is a slight refinement on repeated perfect shuffles.

While (there are two people who haven't met):

  1. Consider the graph where each node is a guest and edge (A, B) exists if A and B have NOT sat at the same table. Find all the connected components of this graph. If there are any connected components of size < tablesize, schedule those connected components at tables. Note that even this is actually an instance of a hard problem known as Bin packing, but first fit decreasing will probably be fine, which can be accomplished by sorting the connected components in order of biggest to smallest, and then putting them each of them in turn at the first table where they fit.
  2. Perform a random permutation of the remaining elements. (In other words, seat the remaining people randomly, which at first will be everyone.)
  3. Increment counter indicating number of rounds.

Repeat the above for a while until the number of rounds seems to converge.

Martin Hock
  • 944
  • 4
  • 5