Skip to content

Instantly share code, notes, and snippets.

@spaghetti-source
Last active August 29, 2015 14:07
Show Gist options
  • Save spaghetti-source/3f22ec4da36f1cc68a46 to your computer and use it in GitHub Desktop.
Save spaghetti-source/3f22ec4da36f1cc68a46 to your computer and use it in GitHub Desktop.
Draw a number [0...n) from a loaded dice (Vose's alias method)
//
// Draw a number [0...n) from a loaded dice (Vose's alias method)
//
#include <iostream>
#include <vector>
using namespace std;
unsigned int xor32() {
static unsigned long y = 2463534242UL;
y^=(y<<13); y^=(y>>17);
return (y^=(y<<15));
}
double urand() {
return xor32() / (1.0 + UINT_MAX);
}
struct dice {
vector<double> p;
vector<int> a;
dice(const vector<double> &p_) : p(p_) {
int n = p.size(); a.resize(n);
vector<int> S, L;
for (int i = 0; i < n; ++i) {
p[i] *= n;
if (p[i] < 1) S.push_back(i);
else L.push_back(i);
}
while (!S.empty() && !L.empty()) {
int s = S.back(); S.pop_back();
int l = L.back(); L.pop_back();
p[l] += p[s] - 1; a[s] = l;
if (p[l] < 1) S.push_back(l);
else L.push_back(l);
}
for (auto s: S) p[s] = 1.0;
for (auto l: L) p[l] = 1.0;
}
int draw() {
int k = p.size() * urand();
return urand() < p[k] ? k : a[k];
}
};
int main() {
dice d({1.0/10.0, 2.0/10.0, 3.0/10.0, 4.0/10.0});
int m = 1000000;
int count[4] = {0};
for (int i = 0; i < m; ++i) {
count[d.draw()] += 1;
}
for (int i = 0; i < 4; ++i) {
cout << 1.0 * count[i] / m << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment