3

我正在自学 Python,并编写了一个用于交换圣诞礼物的小脚本(这不是家庭作业)。我的家人喜欢每个人送一件礼物给一个同性别的人。以下脚本大部分时间都有效,但有时会因无限递归而失败。我不知道为什么,因为我认为基本情况最终会得到满足。

import random

family = {'Joe': 'm', 'Jane': 'f', 'John': 'm', 'Jill': 'f', 'James': 'm', 'Jade': 'f'}
receivers = family.copy()
givers = family.copy()

def match(giver):
    index = random.randrange(len(receivers))
    giverGender = givers[giver]
    receiver = receivers.keys()[index]
    receiverGender = receivers.values()[index]

    if giver != receiver and giverGender == receiverGender:
        del receivers[receiver]
        return giver + ' to ' + receiver
    else:
        return match(giver)

# main program
for i in givers:
    print match(i)

这是错误(编辑添加完整错误):

Traceback (most recent call last):
  File "C:\...\christmasGifts.py", line 22, in <module>
    print match(i)
  File "C:\...\christmasGifts.py", line 18, in match
    return match(giver)

  ...

  File "C:\...\christmasGifts.py", line 18, in match
    return match(giver)
  File "C:\...\christmasGifts.py", line 9, in match
  index = random.randrange(len(receivers))
  File "C:\Python27\lib\random.py", line 184, in randrange
istart = int(start)
RuntimeError: maximum recursion depth exceeded while calling a Python object

感谢您的任何帮助。

4

5 回答 5

6

首先让我们只考虑女性。如果您的程序运行并将 Jane 与 Jill 匹配,然后将 Jill 与 Jane 匹配,Jane 是唯一剩下的女性,并且因为她无法匹配自己,您的程序将无限期地运行而没有匹配。

让我提出一种替代方法来解决您的问题。随机打乱你的送礼者/接受者的顺序,让每个人给列表中的以下人送礼,并让列表中的最后一个人给第一人送礼。看起来像这样:

from random import shuffle
women = ['Jane', 'Jill', 'Jade']
shuffle(women)
print women[-1] + ' to ' + women[0]
for i in range(len(women) - 1):
    print women[i] + ' to ' + women[i+1]
于 2012-11-16T17:53:49.900 回答
2

简对吉尔和吉尔对简

翡翠送给谁?

于 2012-11-16T17:53:31.927 回答
0

这是脚本的简单迭代变体。它工作得很好。

作为一个假设,我认为,基于概率论,有时你只是调用 match 函数太多次,所以它会导致程序达到递归限制

import random

family = {'Joe': 'm', 'Jane': 'f', 'John': 'm', 'Jill': 'f', 'James': 'm', 'Jade': 'f'}
receivers = family.copy()
givers = family.copy()

def match(giver):
    giverGender = givers[giver]

    Found = False
    while not Found:
        index = random.randrange(len(receivers))
        receiver = receivers.keys()[index]
        receiverGender = receivers.values()[index]
        if giver != receiver and giverGender == receiverGender:
            Found = True
            del receivers[receiver]
    return giver + ' to ' + receiver


# main program
if __name__=='__main__':
    for i in givers:
        print match(i)
于 2012-11-16T17:54:34.330 回答
0

有一种更容易理解的方法:

from itertools import izip_longest
from random import shuffle

family = {
    'Joe': 'm',
    'Jane': 'f',
    'John': 'm',
    'Jill': 'f',
    'James': 'm',
    'Jade': 'f'
}

females = [k for k, v in family.iteritems() if v == 'f']
for num in range(5):
    shuffle(females) # muck up the order a bit
    print list(izip_longest(females, females[1:], fillvalue=females[0]))

[('Jade', 'Jill'), ('Jill', 'Jane'), ('Jane', 'Jade')]
[('Jane', 'Jill'), ('Jill', 'Jade'), ('Jade', 'Jane')]
[('Jade', 'Jane'), ('Jane', 'Jill'), ('Jill', 'Jade')]
[('Jade', 'Jane'), ('Jane', 'Jill'), ('Jill', 'Jade')]
[('Jill', 'Jane'), ('Jane', 'Jade'), ('Jade', 'Jill')]
于 2012-11-16T18:10:00.543 回答
0

下面的版本实际上允许更多的选择可能性。

from random import randint

giver = ['Jane', 'Jill', 'Jade', 'Nicole', 'Charlotte']

receiver = [i for i in giver]

def match(giver, receiver):
    for i in giver:

        #get random receiver
        rec = receiver[randint(0,len(receiver)-1)]

        #check to see if only two remain, so person doesn't pick self in loop.
        if len(receiver) == 2:
            rec = receiver[1]

        #make sure person doesn't select themself.
        while i == rec:
            rec = receiver[randint(0,len(receiver)-1)]

        print i + " gives to " + rec
        #reduce receiver pool
        receiver.remove(rec)

编辑:不知何故,我认为这破坏了在感恩节戴帽子画画的乐趣.... :)

于 2012-11-16T20:17:02.660 回答