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.

#!/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. This is truly geektastic ! Idea for Easter – python code to randomise GPS locations to hide the Easter eggs.

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

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

  3. 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.

  4. 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 *