Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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.

http://en.wikipedia.org/wiki/Secret_Santa

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.

Rules:

  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))
end

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:

{"Nick"=>"Darren",
 "Paul"=>"Nick",
 "Kevin"=>"Paul",
 "Rowan"=>"Kevin",
 "Atif"=>"Rowan",
 "Oliver"=>"Atif",
 "Darren"=>"Oliver"}
share|improve this question
    
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? –  Peter Taylor Nov 26 '12 at 19:26
    
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. –  Oliver Atkinson Nov 26 '12 at 19:29
1  
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? –  ardnew Nov 26 '12 at 21:03
    
It's not quite exactly the same, the other one has a hardcoded list. –  marinus Nov 26 '12 at 21:53
    
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) –  Oliver Atkinson Nov 26 '12 at 21:55
add comment

marked as duplicate by dmckee Nov 26 '12 at 21:19

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

3 Answers

k (29 20 chars)

{i!(1_i),*i:(-#x)?x}

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

Example

k){i!(1_i),*i:(-#x)?x}`person1`person2`person3`person4`person5
person2| person1
person5| person3
person4| person2
person1| person5
person3| person4

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

share|improve this answer
    
very small - where can i get a copy of k to run this? –  Oliver Atkinson Nov 26 '12 at 20:19
    
You can grab an evaluation version of the interpreter here kx.com/software.php . It's one interpreter for both q and k –  slackwear Nov 26 '12 at 20:27
add comment
    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]]);
share|improve this answer
add comment

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)]

Usage

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

Update

r=ARGV.shuffle!.dup;p ARGV.zip(r<<r.shift)
share|improve this answer
    
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. –  air_blob Nov 27 '12 at 9:34
    
This can be shortened to 38 by replacing ARGV by $* r=$*.shuffle!.dup;p $*.zip(r<<r.shift) –  Gazler Nov 21 '13 at 10:58
add comment

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