我正在教自己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
感谢您的帮助。
答案 0 :(得分: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]
答案 1 :(得分:2)
Jane对Jill和Jill对Jane
Jade是谁给的?
答案 2 :(得分:0)
以下是脚本的简单迭代变体。它运作得很好。
作为一个假设我认为,基于概率论,有时你只需要调用匹配函数太多次,因此它会导致程序达到递归限制
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)
答案 3 :(得分: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')]
答案 4 :(得分: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)
编辑:我不知何故认为这会破坏在感恩节时从帽子上画画的乐趣....:)