UPDATE: The 2011 Secret Santa Name Picker Script

Jennifer Payne | November 22nd, 2011

Last year, we published the source code we used to draw names out of our virtual hat to decide who would be giving a gift to whom as part of our annual t-shirt exchange tradition. However, a quick glance at that old code reveals its problems:

1. It’s inefficient. It uses brute force to match a set of givers to a set of recipients, then it checks to see that no one was assigned to give a gift to themselves. This works OK for small sets, but for larger sets it is very inefficient.

2. It creates the potential that two people will exchange gifts with each other. This is not a bad thing in and of itself; it’s just that if you think about the entire set in terms of a graph, the graph has the potential to lose connectivity. In larger sets, you may have many subsets of gift exchangers without any connectivity between each group. This would be particularly bad if you were trying to create the world’s largest gift exchange, as reddit is attempting to do this year with its Secret Santa program; it would be a shame if you were trying to break the record only to discover that rather than one humongous group exchanging gifts, you had 2 or 3 unconnected groups exchanging gifts. Something like that in a small group would look like the following:

Ideally, we’d prefer to have something like this (a directed cycle graph):

Fortunately, something like this in programming is easy—much easier than what what we tried to do last year. (In my defense, I did write last year’s script in a few minutes without thinking about it much.)

To represent a directed cycle graph as a data structure, you can use a circularly linked list. For the very simple code implementation below, I’m going to use a shuffled array and iterate through it once. For the last node, I’m going to use a stored reference to the first node to complete the circle. However, for more advanced programs, you would probably use a modified version of SplDoublyLinkedList where nextNode for the last node always returns the first node (and prevNode for the first node always returns the last node).


$emails = array(

// shuffle the emails

// grab the first person
$giver = $first_person = array_shift($emails);

while (null != ($givee = array_shift($emails))) {

give($giver, $givee);

// now the givee becomes the giver
$giver = $givee;

// once we reach this point, the final givee is the first person
give($giver, $first_person);

function give($giver, $givee) {
echo(sprintf('%s gives to %s', $giver, $givee));

See, much simpler than last years. Happy holidays, folks!

Leave a Reply

Intervals Blog

A collection of useful tips, tales and opinions based on decades of collective experience designing and developing web sites and web-based applications.

What is Intervals?

Intervals is online time, task and project management software built by and for web designers, developers and creatives.
Learn more…

John Reeve
Author Profile
John Reeve

John is a co-founder, web designer and developer at Pelago. His blog posts are inspired by everyday encounters with designers, developers, creatives and small businesses in general. John is an avid reader and road cyclist.
» More about John
» Read posts by John

Jennifer Payne
Author Profile
Jennifer Payne

Jennifer is the Director of Quality and Efficiency at Pelago. Her blog posts are based largely on her experience working with teams to improve harmony and productivity. Jennifer is a cat person.
» More about Jennifer
» Read posts by Jennifer

Michael Payne
Author Profile
Michael Payne

Michael is a co-founder and product architect at Pelago. His contributions stem from experiences managing the development process behind web sites and web-based applications such as Intervals. Michael drives a 1990 Volkswagen Carat with a rebuilt 2.4 liter engine from GoWesty.
» More about Michael
» Read posts by Michael

Videos, tips & tricks