Skip to content

Instantly share code, notes, and snippets.

@joriki
Created October 12, 2012 21:09
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 joriki/3881546 to your computer and use it in GitHub Desktop.
Save joriki/3881546 to your computer and use it in GitHub Desktop.
Calculation and simulation of the probability of a relatively uniform draw; see http://math.stackexchange.com/questions/211687
import java.math.BigInteger;
import java.util.Random;
public class Question211687 {
final static int n = 100;
final static int m = 10;
final static int perKind = 100;
final static int min = 8;
final static int max = 12;
final static int total = m * perKind;
final static int R = max - min;
final static int [] counts = new int [m];
final static Random random = new Random ();
static int count = 0;
static BigInteger sum = BigInteger.ZERO;
static void recurse (int index,int left) {
if (left < min * (m - index) || left > max * (m - index))
return;
if (index == m) {
if (left == 0) {
count++;
BigInteger product = BigInteger.ONE;
for (int i = 0;i < m;i++)
for (int j = min;j < max;j++)
product = product.multiply (BigInteger.valueOf (counts [i] <= j ? j + 1 : perKind - j));
sum = sum.add (product);
}
return;
}
for (counts [index] = min;counts [index] <= max;counts [index]++)
recurse (index + 1,left - counts [index]);
}
static BigInteger binomial (int n,int k) {
BigInteger binomial = BigInteger.ONE;
for (int i = 0;i < k;i++) {
binomial = binomial.multiply (BigInteger.valueOf (n - i));
binomial = binomial.divide (BigInteger.valueOf (i + 1));
}
return binomial;
}
static BigInteger factorial (int n) {
BigInteger factorial = BigInteger.ONE;
for (int i = 2;i <= n;i++)
factorial = factorial.multiply (BigInteger.valueOf (i));
return factorial;
}
public static void main (String [] args) {
recurse (0,n);
BigInteger numerator = factorial (perKind);
BigInteger denominator = factorial (max).multiply (factorial (perKind - min));
BigInteger num = sum;
BigInteger den = binomial (total,n);
for (int i = 0;i < m;i++) {
num = num.multiply (numerator);
den = den.multiply (denominator);
}
BigInteger gcd = num.gcd (den);
num = num.divide (gcd);
den = den.divide (gcd);
System.out.println (num + " / " + den);
int precision = 1000000;
System.out.println ("p = " + num.multiply (BigInteger.valueOf (precision)).add (BigInteger.valueOf (precision / 2)).divide (den).doubleValue () / precision);
System.out.println (count + " admissible combinations");
final int ntrials = 10000000;
int nsuccesses = 0;
outer:
for (int i = 0;i < ntrials;i++) {
boolean [] used = new boolean [total];
int [] npebbles = new int [m];
for (int j = 0;j < n;j++) {
int pebble;
do
pebble = random.nextInt (total);
while (used [pebble]);
used [pebble] = true;
npebbles [pebble / perKind]++;
}
for (int np : npebbles)
if (min > np || np > max)
continue outer;
nsuccesses++;
}
System.out.println ("p ~ " + nsuccesses / (double) ntrials);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment