How to create a random Secret Santa list in R

Thanks to Murray Pollock for his feedback.

Method 1: avoiding “A has B and B has A”.

The following R code shows how to create a random Secret Santa list by:

  1. Randomising the original list of names.
  2. Assigning sequentially the names in the randomised list (First has Second, Second has Third, …, and Last has First).

The first step guarantees that the list will not be biased by the person who created the original list of names, while the second step guarantees that no one will be assigned to himself/herself. This method also avoids cases when “A has B and B has A”.

# A list of names
names = c("Pancho Villa","William Shakespeare","Don Quijote","Madame Bovary","Thomas Bayes","Richard Wagner")
# length of the list
n <- length(names)

# Randomise the list
randlist <- sample(names)
# Creating the Secret Santa list based on assigning the names sequentially on the randomised list
# The last element in the randomised list is assigned to the first element

ListSS <- matrix(0,ncol=2,nrow=n) # Initialise the list
# Assigning the names
for( i in 1:(n-1))  ListSS[i,] <- c(randlist[i],randlist[i+1])
ListSS[n,] <- c(randlist[n],randlist[1])
colnames(ListSS) <- c("Name", "Has")

# Raw list
ListSS
##      Name                  Has                  
## [1,] "Pancho Villa"        "William Shakespeare"
## [2,] "William Shakespeare" "Richard Wagner"     
## [3,] "Richard Wagner"      "Madame Bovary"      
## [4,] "Madame Bovary"       "Don Quijote"        
## [5,] "Don Quijote"         "Thomas Bayes"       
## [6,] "Thomas Bayes"        "Pancho Villa"
# Presenting the list in a nicer format
library(knitr)
kable(ListSS)
Name Has
Pancho Villa William Shakespeare
William Shakespeare Richard Wagner
Richard Wagner Madame Bovary
Madame Bovary Don Quijote
Don Quijote Thomas Bayes
Thomas Bayes Pancho Villa

Method 2: Urn-drawing style avoiding “A has A”.

The following R code shows how to create a random Secret Santa list by sampling one person at a time from the remaining persons, as you would do with an urn.

# A list of names
names = c("Pancho Villa","William Shakespeare","Don Quijote","Madame Bovary","Thomas Bayes","Richard Wagner")
# length of the list
n <- length(names)

valid <-1
while(valid>0){

names2 <- vector()
names2[1] <- sample(names[-1],1)
for(i in 2:(n-1)){
  names2[i] <- sample(setdiff(names[-i],names2),1)
}

names2[n] <- setdiff(names,names2)

valid <- sum((names==names2)*1) # checking if someone drew himself

}

# Raw list
ListSS <- cbind(names,names2)
colnames(ListSS) <- c("Name", "Has")

# Presenting the list in a nicer format
library(knitr)
kable(ListSS)
Name Has
Pancho Villa Richard Wagner
William Shakespeare Thomas Bayes
Don Quijote Madame Bovary
Madame Bovary Pancho Villa
Thomas Bayes William Shakespeare
Richard Wagner Don Quijote