Skip to content

Instantly share code, notes, and snippets.

@tartakynov
Last active January 23, 2018 12:04
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 tartakynov/68ad21dbdc891ad53e6dc61084d579ad to your computer and use it in GitHub Desktop.
Save tartakynov/68ad21dbdc891ad53e6dc61084d579ad to your computer and use it in GitHub Desktop.
Assign to A/B test
import com.google.common.hash.{Hashing, HashFunction};
/**
* Deterministic algorithm for assigning given variables to variants A or B with given probability.
*
* @param id The experiment's identifier
* @param pA Probability of A (probability of B is 'pB = 1.0 - pA').
*/
class Experiment(val id: String, pA: Float) {
/**
* CRC32 is very fast and not significantly worse that cryptographic
* hash functions in terms of uniformity of the outputs.
*
* Source michiel.buddingh.eu/distribution-of-hash-values
*/
private val hashFunction: HashFunction = Hashing.crc32()
private val threshold: Int = (Int.MaxValue - (4294967295L * pA)).toInt
def isVariantA(variables: String*): Boolean = hashVariables(variables) > threshold
protected def hashVariables(variables: Seq[String]): Int = {
val str = s"$id:${variables.mkString(":")}"
hashFunction.hashString(str, StandardCharsets.UTF_8).asInt()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment