Last active
August 29, 2015 14:20
-
-
Save need12648430/9b36ed78fe2bc8753afc to your computer and use it in GitHub Desktop.
Linear congruential generator (Seedable PRNG) with weighted choices and shuffling in 1.4kb of clean JS.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var LCG = (function () { | |
var c = 0x93456789, a = 0x169659, mod, mask, r; | |
mask = (mod = Math.pow(2, 31)) - 1; | |
function LCG(seed) { | |
this.seed = seed || new Date().getTime(); | |
} | |
LCG.prototype = { | |
nextInt: | |
function () { | |
r = this.seed + c; | |
this.seed = (this.seed * a + c) & mask; | |
r = ((r ^ (r >>> 16)) * a) & mask; | |
return r ^ (r >>> 16); | |
}, | |
nextFloat: | |
function () {return this.nextInt() / mod}, | |
rangeInt: | |
function (start, end) { | |
var n; | |
while ((n = this.nextInt()) > mod - mod % (end - start)) ; | |
return start + n % (end - start); | |
}, | |
rangeFloat: | |
function (start, end) {return start + this.nextFloat() * (end - start);}, | |
choose: | |
function (set, weights) { | |
if (!weights) return set[LCG.prototype.rangeInt(0, set.length)]; | |
if (set.length != weights.length) throw "Set length must match weights length."; | |
var i, t, s, a; | |
for (t = i = 0; i < set.length; t += weights[i ++]); | |
s = this.rangeFloat(0, t); | |
for (i = a = 0; a < t; a += weights.shift(i ++)) | |
if (s >= a && s < a + weights[0]) | |
return set[i]; | |
}, | |
shuffle: | |
function (set) { | |
for ( | |
var copy = set.slice(0), out = []; | |
copy.length > 0; | |
out.push(copy.splice(this.nextInt() % copy.length, 1)[0]) | |
); | |
return out; | |
} | |
}; | |
return LCG; | |
})(); |
Should have done some more studying before attempting this. Maybe looked at some existing implementations - but thank you.
This looks really cool. Definitely going to star this for use in a future project.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
2^n generator has a flaw with lower bits, which have a smaller period.
This could be fixed by additional shuffling:
Even with this additional shuffling, nodejs runs this faster than original code, cause
&
used instead of%
.