Skip to content

Instantly share code, notes, and snippets.

@greghaskins
Last active May 1, 2019 13:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save greghaskins/e4925dfa8496ea3a6e3c9e39ee11ce21 to your computer and use it in GitHub Desktop.
Save greghaskins/e4925dfa8496ea3a6e3c9e39ee11ce21 to your computer and use it in GitHub Desktop.
raffle.py: Randomly choose N unique entries from a list

raffle.py

This script will run a raffle with the following rules:

  1. A predefined number of winners will be selected
  2. People are allowed to have multiple entries in the raffle
  3. However, each person can only win once
  4. Drawings are made at random

Mathematical Properties

It's possible to work out your statistical odds of winning based on the number of winners, how many entries you have, and the total number of entries. I'll leave that as an exercise for the reader.

#!/usr/bin/env python
import random
# ------------------
# Raffle algorithm
# ------------------
def raffle(number_of_winners, entries, random_source):
winners = set() # hold unique values only
hat = list(entries)
while len(winners) < number_of_winners:
hat_size = len(hat)
if hat_size == 0:
raise ValueError("Not enough unique entries for {} winners".format(number_of_winners))
random_index = random_source.randrange(hat_size)
drawn_entry = hat.pop(random_index) # get and remove random_index
winners.add(drawn_entry)
return winners
# ------------------------
# Command-line interface
# ------------------------
USAGE="""USAGE: raffle.py number_of_winners [entries_file...]
number_of_winners (required):
The number of unique winners for the raffle
entries_file (optional, repeated):
Text file(s) with one raffle entry per line
If none given, entries will be read from standard input (`-`)
"""
if __name__ == '__main__':
import sys
import os
import fileinput
try:
number_of_winners = int(sys.argv[1])
entry_files = sys.argv[2:]
except (IndexError, ValueError) as e:
sys.stderr.write(USAGE)
sys.exit(1)
entries = [line.strip() for line in fileinput.input(files=entry_files)]
seed = os.environ.get('RANDOM_SEED')
random_source = random.Random(seed) if seed else random.SystemRandom()
sys.stderr.write("Selecting {} winners from {}...\n".format(number_of_winners, entries))
winners = raffle(number_of_winners, entries, random_source)
print("\n".join(winners))
@cbibbs
Copy link

cbibbs commented Apr 25, 2019

Can you add an example of the entry file?

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