Skip to content

Instantly share code, notes, and snippets.

@s5b
Last active December 5, 2015 20:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save s5b/4138054 to your computer and use it in GitHub Desktop.
Save s5b/4138054 to your computer and use it in GitHub Desktop.
KrisKringulator for creating your Kris Kringle so that even you don't know who got whom. (2015 version)
#!/usr/bin/python
"""
This is the KrisKringulator 2015.
It is a script that uses python (2.7+) to create a set of files containing the
name of the person for whom a participant in the Kris Kringle needs to buy a
gift. That is, it creates a file named after the buyer, with the name of the
buyer's recipient inside the file.
Based on an algorithm mentioned by Ryan Sattler.
This is designed to preserve the anonimity of all receivers. Simply send the
resulting files to the names of the file.
To use the application, by example:
>>> python kk.py outcome peter fred joanne gary jane
This will generate the following files:
./outcome/fred.txt
./outcome/gary.txt
./outcome/jane.txt
./outcome/joanne.txt
./outcome/peter.txt
"""
import sys
import random
import os
def create_gifting(result_dir, participant_from, participant_to):
with open(os.path.join(result_dir, participant_from + '.txt'), 'wt') as f:
f.write("%s buys for %s.\n" % (participant_from, participant_to))
f.close()
def initialize_result_directory(result_dir):
if os.path.exists(result_dir):
print "The result directory must not already exist:", result_dir
exit()
os.mkdir(result_dir)
if len(sys.argv) < 3 :
print "Usage:", sys.argv[0], "result_directory participant1 participant2 ..."
result_dir = sys.argv[1]
initialize_result_directory(result_dir)
participants = sys.argv[2:]
random.shuffle(participants)
for index in range(0, len(participants) - 1):
create_gifting(result_dir, participants[index], participants[index + 1])
create_gifting(result_dir, participants[len(participants) - 1], participants[0])
@s5b
Copy link
Author

s5b commented Dec 24, 2012

Gosh... There was a bug in the KrisKringulator! Thanks to Brett Herlihy for pointing out the symptom.

You see, the original code ran into a problem when the last remaining unmatched participant was the same as the last participant in the list. That is, all other participants had been matched with each other except the last participant. And since the same participant can't be matched to itself, then the last match would be blank - because a participant can't buy for themselves.

To fix the code I have added a test that checks if the last participant is contained in the final two remaining participants. If so, then the final two remaining participants are matched with each other. This solves the problem of not matching the last participant with themselves, but causes a slightly higher probability of the last two participants being matched together.

To mitigate the match probability problem, the participants are shuffled before being matched. This prevents the order in which the participants are entered on the command line from affecting the outcome.

@s5b
Copy link
Author

s5b commented Nov 23, 2014

Updated the KrisKringulator to be implemented in python, instead of ruby. (Python is usually already installed on your *nix distribution, unlike ruby.) And the algorithm uses a different approach, as mentioned by Ryan Sattler. See the comments at the top of the gist to understand how to use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment