Possible Duplicate:
Holiday Gift Exchange

Background: Secret Santa is a Western Christmas tradition in which members of a group or community are randomly assigned a person to whom they anonymously give a gift.


Ok, me and my work colleges did this today during our lunch hour - we made a secret algorithm santa pick random gifters and receivers.

Think of this question as a Christmas Programming Challenge to see who can come up with some of the most elegant solutions for this problem.

Input: The input should be an array ['Oliver', 'Paul', 'Rowan', 'Darren', 'Nick', 'Atif', 'Kevin']

Output A representation of something similar to key value pairs for the gifter and receiver. e.g.

Oliver -> Darren,
Paul -> Nick,
Rowan -> Kevin
Kevin -> Atif,
Darren -> Paul,
Nick -> Oliver,
Atif -> Rowan

Deadline: 15th December (for those late christmas shoppers)

Remember: you cannot have a person choosing themselves and the program must not spiral off into an infinite loop when gifter == receiver when there is only one person left.


  1. Must not have duplicates
  2. Must be random (we all have different views on what is random - but you get my gist)
  3. No Language constraints
  4. Have fun

Here is mine (not golfed) in ruby:

require 'pp'

def move(array, from, to)
  array.insert(to, array.delete_at(from))

gifters = ['Oliver', 'Paul', 'Rowan', 'Darren', 'Nick', 'Atif', 'Kevin'].shuffle!
recievers = gifters.dup

move recievers, recievers.count - 1, 0

pp Hash[gifters.zip recievers]

which spits out:

  • \$\begingroup\$ Input? Or do you want it hard-coded, as in your example? Does the resulting derangement have to be a single cycle, as implemented by your code, or can it be a product of disjoint cycles? \$\endgroup\$ – Peter Taylor Nov 26 '12 at 19:26
  • \$\begingroup\$ I should have made it clearer in my post. The input should be an array ['Oliver', 'Paul', 'Rowan', 'Darren', 'Nick', 'Atif', 'Kevin'] and it can be a product of disjoint cycles - the rules are pretty open. \$\endgroup\$ – StudleyJr Nov 26 '12 at 19:29
  • 1
    \$\begingroup\$ this is kinda trivial for a code challenge tag, and only one answer appears to be golf'd, so uh what's the objective here? \$\endgroup\$ – ardnew Nov 26 '12 at 21:03
  • \$\begingroup\$ It's not quite exactly the same, the other one has a hardcoded list. \$\endgroup\$ – marinus Nov 26 '12 at 21:53
  • \$\begingroup\$ the challenge is for fun - to produce the code in different languages with different approaches. The approach with the best intuitive wins (probably based on up votes, so the mass can decide) \$\endgroup\$ – StudleyJr Nov 26 '12 at 21:55

k (29 20 chars)


{i!@[i:(-:#x)?x;,/|2 0N#!#x]}


person2| person1
person5| person3
person4| person2
person1| person5
person3| person4

Explanation - as above, shuffles list and maps to rotation of itself.

| improve this answer | |
  • \$\begingroup\$ very small - where can i get a copy of k to run this? \$\endgroup\$ – StudleyJr Nov 26 '12 at 20:19
  • \$\begingroup\$ You can grab an evaluation version of the interpreter here kx.com/software.php . It's one interpreter for both q and k \$\endgroup\$ – skeevey Nov 26 '12 at 20:27
    NSMutableArray *people =
    [NSMutableArray arrayWithArray:@[@"Oliver", @"Paul", @"Rowan", @"Darren", @"Nick", @"Atif", @"Kevin"]];
    [people sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
         return (arc4random_uniform(3)-1);

    for (int i = 0;  i < [people count]; i++)
        NSLog(@"%@ gifts %@", people[i], people[(i+1)%[people count]]);
| improve this answer | |

Ruby - 161 42 chars

#!/usr/bin/env ruby
require 'csv'

gifters = CSV.read(ARGV[0]).first

receivers = gifters.shuffle!.dup
puts Hash[gifters.zip(receivers << receivers.shift)]


./secret_santa path_to_some_csv
=> {"Edward"=>"Alan", "Alan"=>"Charlie", "Charlie"=>"Dave", "Dave"=>"Brett", "Brett"=>"Edward"}


r=ARGV.shuffle!.dup;p ARGV.zip(r<<r.shift)
| improve this answer | |
  • \$\begingroup\$ As this is a code golf problem, I added the language and char count to your answer. I think there's still potential to shorten the code, for example using single char variable names or removing line breaks. \$\endgroup\$ – codeporn Nov 27 '12 at 9:34
  • \$\begingroup\$ This can be shortened to 38 by replacing ARGV by $* r=$*.shuffle!.dup;p $*.zip(r<<r.shift) \$\endgroup\$ – Gazler Nov 21 '13 at 10:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.