【问题标题】:Speed dating algorithm快速约会算法
【发布时间】:2010-11-01 09:44:00
【问题描述】:

我在一家咨询机构工作,大部分时间都在客户所在地。因此,我很少见到我的同事。为了更好地了解彼此,我们将安排一次晚宴。会有很多小桌子,所以人们可以聊天。为了在聚会期间与尽可能多的人交谈,每个人都必须每隔一段时间换桌一次,比如每小时一次。

如何编写一个创建表切换时间表的程序?只是给你一些数字;在这种情况下,大约有 40 人,每张桌子最多可以有 8 人。但是,算法当然需要通用

【问题讨论】:

    标签: algorithm language-agnostic permutation combinations


    【解决方案1】:

    这是一个想法
    从第一人称的角度来看的第一部作品.. 我们称他为 X
    X 必须与房间里的所有其他人会面,因此我们应该将剩余的人分成 n 组(其中 n = #_of_people/capacity_per_table )并让他每次迭代都坐在其中一个组中
    既然 X 已经处理好了,我们再考虑下一个人 Y
    WLOG Y 是 X 在第一次迭代中必须坐的人。所以我们已经知道 Y 在那个时间范围内的桌子组。然后我们应该把剩下的人分成几组,这样每组每连续一次就和 Y 坐在一起迭代.. 对于每次迭代,X 组和 Y 组没有共同点
    ..我想,如果你继续这样做,你会得到一个最优解(如果存在的话)

    或者,您可以通过给每个人一张卡片来众包问题,他们可以在卡片上写下与他们共进晚餐的所有人的姓名。在活动结束时,向拥有他们卡中的大多数名字

    【讨论】:

      【解决方案2】:

      这听起来像是遗传算法的应用:

      1. 选择随机排列的 40 位客人 - 这是一种座位安排
      2. 重复随机排列 N 次(n 是你在夜间换座位的次数)
      3. 将排列组合在一起 - 这是一个生物体的染色体
      4. 重复你想在一代中繁殖多少生物
      5. 健身得分是每个人在一个晚上看到的人数(或者 - 他们没有看到的人数的倒数)
      6. 使用常规方法培育、变异和引入新的生物体,然后重复,直到得到满意的答案

      你可以在适应度中加入你喜欢的任何其他因素,比如男女比例等等,而不会大大改变底层方法。

      【讨论】:

        【解决方案3】:

        为什么不模仿现实世界?

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

        哦,请注意,有一种类似的算法可以寻找交配对象,据传它对那些没有将所有空闲时间都花在回答编程问题上的 99% 的人有效...

        【讨论】:

          【解决方案4】:

          【讨论】:

            【解决方案5】:

            您可能想看看combinatorial design theory

            【讨论】:

              【解决方案6】:

              直觉上我认为你不能比perfect shuffle 做得更好,但这超出了我喝咖啡前的认知。

              【讨论】:

                【解决方案7】:

                这个很搞笑! :D

                我尝试了不同的方法,但 adi92(卡片 + 奖品)建议的逻辑比我尝试过的任何其他方法都好。

                它是这样工作的:

                1. 一个人来检查所有的桌子
                2. 对于每张有空位的桌子,他会计算他还需要会见多少人,然后选择陌生人较多的一张
                3. 如果两张桌子有相同数量的陌生人,那么这个家伙会选择空位多的一张,这样就有更多的机会结识更多新朋友

                每一轮就座的人的顺序是随机的(这避免了可能的无限循环),这是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'
                

                这将输出如下内容:

                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]
                

                由于随机性,它并不总是带有最少的切换次数,尤其是在人数较多的情况下。然后你应该运行它几次,并以更少的回合获得结果(这样你就不会给聚会上的所有人带来压力:P),而且编写代码很容易:P

                PS: 是的,你可以省下奖金:P

                【讨论】:

                  【解决方案8】:

                  你也可以看看稳定匹配问题。这个问题的解决方案涉及使用最大流算法。 http://en.wikipedia.org/wiki/Stable_marriage_problem

                  【讨论】:

                    【解决方案9】:

                    我不会为遗传算法而烦恼。相反,我会执行以下操作,这是对重复完美洗牌的轻微改进。

                    虽然(有两个人没见过):

                    1. 考虑图中每个节点都是客人,如果 A 和 B 没有坐在同一张桌子上,则存在边 (A, B)。找出这张图的所有connected components。如果有任何大小
                    2. 对剩余元素执行随机排列。 (换句话说,让其余的人随机入座,一开始是每个人。)
                    3. 指示轮数的增量计数器。

                    重复上述操作一段时间,直到轮数似乎收敛。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-12-06
                      • 1970-01-01
                      • 2019-03-19
                      • 2015-03-12
                      • 2012-05-30
                      • 1970-01-01
                      • 2011-09-05
                      相关资源
                      最近更新 更多