Python Gift Circle

Holiday Python geekiness…

If your family (or classroom or workplace) does “gift circles,” where everyone buys a gift for exactly one other person in the group, you could do (and probably already do do) the old “pull a name out of a hat” thing. But that takes setup time: writing down names, cutting them out, finding a hat, passing it around… shouldn’t this process be automated? Here’s a little Python script to get it done quick.

On my MacBook, the script runs for ten people in 27 milliseconds – think of all the egg nog you could drink in the time you save!

Populate the “recipients” list with real names and run ./gift-circle.py.

Update: This script is now available at github.

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/python
import random
 
'''
Gift exchange randomizer in Python.
Step through a list of people and, for each member of that list,
select someone else to be a recipient of their gift. That recipient:
 
    A) Must not be themselves (no self-gifting)
    B) Must not already have been assigned as a recipient
 
Due to randomization, we can't prevent the possibility that 7/8 of people
will all give to each other, leaving the 8th to give to themselves. Therefore
we keep running the function until we get full distribution.
'''
 
def give():
    str = ''
 
    givers = ['Leslie', 'Jamie', 'Avis', 'Jim', 'Amy', 'Scot', 'Mike', 'Miles', 'Buford', 'Momo']
    recipients = list(givers)  # Make a copy
 
    for idx, giver in enumerate(givers):
 
        # Grab random person from the recipients
        recipient = random.choice(recipients)
 
        # Make sure we haven't either randomly chosen the same recipient and giver OR
        # ended up with only one un-gifted person in the list.
        if recipient == giver:
            return False
        else:
            # Remove this recipient from the pool and build the results string
            recipients.remove(recipient)
            str = str + "{idx}: {giver} gives to {recipient}\n".format(
                idx=idx+1, giver=giver, recipient=recipient
                )
    return str
 
 
# Keep trying until we get through the set with no failures
results=give()
while not results:
    results = give()
 
print results

Output looks like this:

1: Leslie gives to Amy
2: Jamie gives to Leslie
3: Avis gives to Momo
4: Jim gives to Jamie
5: Amy gives to Buford
6: Scot gives to Mike
7: Mike gives to Scot
8: Miles gives to Avis
9: Buford gives to Jim
10: Momo gives to Miles

Happy holidays, you big nerd!

8 Replies to “Python Gift Circle”

  1. rand = random.randint(0, (len(recips))-1)
    randomRecip = recips[rand]

    should be written as
    randomRecip = random.choice(recips)

  2. Thanks Bob – Yes, that’s more compact. While I’ve got you, any theories as to why this script fails at random? If you run it again and again, it’ll crash about 10% of the time with “IndexError: list index out of range” – I just can’t see what’s causing that.

  3. Eric, big thanks for reminding me of this and for kicking my butt to finally refactor this to eliminate possible breakage. It’s a totally different script now, and works every time (though I wonder how long it would take to run with a thousand participants).

Leave a Reply

Your email address will not be published. Required fields are marked *