【问题标题】:Secret Santa Program秘密圣诞老人计划
【发布时间】:2013-11-10 20:52:52
【问题描述】:

我们需要创建一个可用于“秘密圣诞老人”游戏的程序:

from random import *
people=[]
while True:
    person=input("Enter a person participating.(end to exit):\n")
    if person=="end": break
    people.append(person)


shuffle(people)
for i in range(len(people)//2):
    print(people[0],"buys for",people[1])

这是我开发的程序。截至目前,如果我输入 3 个人(例如 Bob、Ben、Bill) 它将返回“Ben 为 Bill 购买”,而没有人为 Ben 或 Bob 购买。我目前正试图让它输出“Bob 为 Ben 购买,Ben 为 Bill 购买,Bill 为 Bob 购买”,但到目前为止还没有成功。如果有人可以给我一个提示/基础来设置它,将不胜感激。另外,如果我的代码中有任何错误不允许我完成此操作,您能告诉我吗?谢谢。

【问题讨论】:

    标签: python list random


    【解决方案1】:

    第一个提示,在 for 循环中使用像 0 和 1 这样的常量而不是 i 是没有意义的。

    for i in range(len(people)):
        print(people[i],"buys for",people[(i+1)%(len(people))])
    

    但是,此实现不会为您提供秘密圣诞老人提供的所有可能性。

    假设你输入“Alice”、“Bob”、“Claire”、“David”,你永远不会遇到这样的情况:

    • 爱丽丝为鲍勃买东西
    • 鲍勃为爱丽丝买东西
    • 克莱尔为大卫买东西
    • 大卫为克莱尔买东西

    你只会得到circular permutations,即:

    • 爱丽丝为鲍勃买东西
    • 鲍勃为克莱尔买东西
    • 克莱尔为大卫买东西
    • 大卫为爱丽丝买东西

    等等。

    你需要一些额外的工作来制作一个完美的秘密圣诞老人:)

    【讨论】:

    • 技术上是正确的,我想。但过于可预测而不实用?
    • @JonCarter 你在 OP 的代码中看到对shuffle 的调用了吗?
    • 随机播放是不够的。 @Jon 是对的,结果仅限于循环排列。
    • 谢谢你们的帮助!非常感谢。
    • @btoueg:为什么shuffle 还不够?
    【解决方案2】:

    您正在索引 0 和 1,因此它始终是第一人和第二人被打印。你真正想要的是:

    shuffle(people)
    offset = [people[-1]] + people[:-1]
    for santa, receiver in zip(people, offset):
         print(santa, "buys for", receiver)
    

    【讨论】:

    • 我认为第二个 sn-p 不会做 OP 想要的。
    【解决方案3】:

    假设你有三个人:['Bob', 'Ben', 'Bill']

    In [1]: people = ['Bob', 'Ben', 'Bill']
    

    现在,当您获得此列表的长度时,您正在执行除以 2。这将导致:

    In [2]: len(people) // 2
    Out[2]: 1
    

    这就是为什么你只能得到一行输出。

    您如何获得您想要的秘密圣诞老人结果?以下是一些简单的实现方法的提示:

    • 您需要某种方法来确保不会将两个人分配给同一个人,并且不会将一个人分配给他或她自己。
    • 这可能意味着可能的买家列表和可能的接收者列表 - 将他们一个一个拉下来并找到他们的匹配项,检查人员没有被分配给他们自己。

    【讨论】:

      【解决方案4】:
      from random import *
      
      prompt = "Enter a person participating.(end to exit):\n"
      people = list(iter(lambda:input(prompt), "end"))
      
      shuffle(people)
      people.append(people[0])
      for i in range(len(people) - 1):
          print(people[i],"buys for", people[i + 1])
      

      样本运行

      Enter a person participating.(end to exit):
      A
      Enter a person participating.(end to exit):
      B
      Enter a person participating.(end to exit):
      C
      Enter a person participating.(end to exit):
      end
      A buys for B
      B buys for C
      C buys for A
      

      你可以替换

      people=[]
      while True:
          person=input("Enter a person participating.(end to exit):\n")
          if person=="end": break
          people.append(person)
      

      prompt = "Enter a person participating.(end to exit):\n"
      people = list(iter(lambda:input(prompt), "end"))
      

      他们都在做同样的事情。 iter 函数会继续执行我们作为第一个参数传递的函数,直到匹配到第二个值。

      然后,你这样做

      people.append(people[0])
      

      这是一个循环的东西,最后一个人必须为第一个人购买。 append 将插入到最后。

      for i in range(len(people) - 1):
      

      我们做len(people) - 1,因为如果有n 人,就会有n 购买。在这种情况下,我们在最后添加了第一个人,所以我们减去了一个。终于

      print(people[i],"buys for", people[i + 1])
      

      每个人都必须为列表中的下一个人购买。所以,people[i] 购买了people[i + 1]

      【讨论】:

        【解决方案5】:

        我意识到我的回答有点晚了,这是我自己的secret santa project 我过去几年一直在使用,我的回答可能会有所帮助。我从脚本中剪掉了重要的部分。

        def pick_recipient(group,recipients,single_flag):
                for person in group:
                        gift = random.choice(recipients)
                        if single_flag == 0:
                                while gift in group:
                                        gift = random.choice(recipients)
                        else:
                                while gift in person:
                                        gift = random.choice(recipients)
                        mail_list.append( '%s=%s' %(person,gift))
                        recipients.remove(gift)
                return recipients
        
        if __name__ == "__main__":
                global mail_list
                mail_list = []
        
                #create lists of people, group couples at beginning or end of list and the singles opposite
                all_recipients = ['name_1-CoupleA: name_1-CoupleA@gmail.com','name_2-CoupleA: name_2-CoupleA@gmail.com',
                        'name_3-CoupleB: name_3-CoupleB@hotmail.com','name_4: name_4CoupleB@hotmail.com',
                        'name_5-Single: name_5-Single@gmail.com','name_6-Single: name_6-Single@gmail.com']
        
                #create couples and lists of singles to make sure couples don't get their other half
                #modify the groups to match the list of people from above
                coupleA = all_recipients [0:2]
                coupleB = all_recipients [2:4]
                single = all_recipients [4:]
        
                #keep initial list in tact      
                possible_recipients = all_recipients
        
                #modify the groups to match what the input list is
                possible_recipients = pick_recipient(coupleA,possible_recipients,single_flag=0)
                possible_recipients = pick_recipient(coupleB,possible_recipients,single_flag=0)
                possible_recipients = pick_recipient(single,possible_recipients,single_flag=1)
        
                print mail_list
        

        【讨论】:

          【解决方案6】:

          秘密圣诞老人发现者

          https://github.com/savitojs/secret-santa-finder-script

          要使用这个脚本, 你需要在secret_santa.py 文件中添加你正在玩的候选人的名字。 _from 和 _to 列表应该相同以获得更好的结果。

          更改_from_to 列表

          跑步
          $ ./secret_santa.py
          Hi.. What is your nick name? [ENTER] savsingh
          Hey savsingh!, Hold on!! Searching...
          Any guess... ?
          
          Your secret santa is: bar
          Clear the screen [ENTER]:
          

          等等……

          脚本在这里:

          #!/usr/bin/python
          #===============================================================================
          #
          #          FILE:  secret_santa.py
          # 
          #         USAGE:  ./secret_santa.py
          # 
          #   DESCRIPTION:  It can help you to find your secret santa, add participants name in _from and _to list
          # 
          #  REQUIREMENTS:  python 2.6+, _from list and _to list should be same to work perfectly.
          #        AUTHOR:  Savitoj Singh (savitojs@gmail.com)
          #       VERSION:  1.1
          #       CREATED:  12/21/2016 05:13:38 AM IST
          #      REVISION:  * Initial release
          #                 * Fixed minor bugs
          #=============================================================================== import random import os import time import sys '''Add participants to list'''
          _from = ['bob','foo','bar','savsingh','tom','jack','mac','hex'] '''Add participants to list'''
          _to = ['bob','foo','bar','savsingh','tom','jack','mac','hex']
          
          
          class bcolors:
              HEADER = '\033[95m'
              OKBLUE = '\033[94m'
              OKGREEN = '\033[92m'
              WARNING = '\033[93m'
              FAIL = '\033[91m'
              ENDC = '\033[0m'
              BOLD = '\033[1m'
              UNDERLINE = '\033[4m'
          
          for i in range(len(_from)):
              try:
                  user_name = raw_input('Hi.. What is your nick name? [ENTER] ')
                  if user_name not in _from and user_name not in _to:
                      try:
                        print("")
                        print(bcolors.FAIL + bcolors.BOLD + "Nick name doesn't seem to be in `_from` or `_to` list" + bcolors.ENDC)
                        print(bcolors.HEADER + "\nDo you expect me to look in galaxy ? It may take many x'mas to retrive results :P" + bcolors.ENDC)
                        break
                      except:
                        pass
                  else:
                      print('Hey ' + bcolors.OKBLUE + bcolors.BOLD + str(user_name) + bcolors.ENDC + '!, Hold on!! Searching...')
                      random.shuffle(_from)
                      _from.remove(user_name)
                      print(bcolors.WARNING + 'Any guess... ?' + bcolors.ENDC)
                      print('')
                      time.sleep(1)
                      a = random.choice(_to)
                      while str(a) == str(user_name):
                          a = random.choice(_to)
                      _to.remove(a)
                      print(bcolors.BOLD + 'Your secret santa is: ' + bcolors.ENDC + bcolors.OKGREEN + bcolors.BOLD + str(a) + bcolors.ENDC)
                      raw_input('Clear the screen [ENTER]: ')
                      os.system('reset')
              except:
                  print(bcolors.FAIL + bcolors.BOLD + "\n\nOops!!, Something went wrong..." + bcolors.ENDC)
                  sys.exit(1)
          

          【讨论】:

            猜你喜欢
            • 2010-09-21
            • 2016-05-23
            • 2022-01-12
            • 2022-01-15
            • 1970-01-01
            • 2012-01-26
            • 2017-04-24
            • 2022-11-17
            • 1970-01-01
            相关资源
            最近更新 更多