Here's the Java code I eventually went with. Comments/corrections welcome.
// n = digits, k = weight, m = position.
public static BigInteger combinadic(int n, int k, BigInteger m) {
BigInteger out = BigInteger.ZERO;
for (; n > 0; n--) {
BigInteger y = nChooseK(n - 1, k);
if (m.compareTo(y) >= 0) {
m = m.subtract(y);
out = out.setBit(n - 1);
k -= 1;
}
}
return out;
}
// Algorithm borrowed (and tweaked) from: http://stackoverflow.com/a/15302448/823393
public static BigInteger nChooseK(int n, int k) {
if (k > n) {
return BigInteger.ZERO;
}
if (k <= 0 || k == n) {
return BigInteger.ONE;
}
// ( n * ( nChooseK(n-1,k-1) ) ) / k;
return BigInteger.valueOf(n).multiply(nChooseK(n - 1, k - 1)).divide(BigInteger.valueOf(k));
}
It certainly generates k-bit numbers when given a number between ${0}$ and ${n \choose k}$.
I chose an LFSR using a tap of order sufficient to exceed ${95 \choose 15}$ (an order 57 primitive polynomial) and rejected any that did not contain the correct number of bits. With this mechanism, generating the first 1,000 n=95 k=15 combinations produced 285 rejects, a perfectly acceptable rate for me.