Auto
This commit is contained in:
117
node_modules/deck/README.markdown
generated
vendored
Normal file
117
node_modules/deck/README.markdown
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
deck
|
||||
====
|
||||
|
||||
Uniform and weighted shuffling and sampling for node.
|
||||
|
||||
examples
|
||||
========
|
||||
|
||||
uniform shuffle
|
||||
---------------
|
||||
|
||||
shuffle.js:
|
||||
|
||||
var deck = require('deck');
|
||||
var xs = deck.shuffle([ 1, 2, 3, 4 ]);
|
||||
console.log(xs);
|
||||
|
||||
output:
|
||||
|
||||
$ node shuffle.js
|
||||
[ 1, 4, 2, 3 ]
|
||||
|
||||
uniform sample
|
||||
--------------
|
||||
|
||||
pick.js:
|
||||
|
||||
var deck = require('deck');
|
||||
var x = deck.pick([ 1, 2, 3, 4 ]);
|
||||
console.log(x);
|
||||
|
||||
output:
|
||||
|
||||
$ node pick.js
|
||||
2
|
||||
|
||||
weighted shuffle
|
||||
----------------
|
||||
|
||||
wshuffle.js:
|
||||
|
||||
var deck = require('deck');
|
||||
var xs = deck.shuffle({
|
||||
a : 10,
|
||||
b : 8,
|
||||
c : 2,
|
||||
d : 1,
|
||||
e : 1,
|
||||
});
|
||||
console.log(xs);
|
||||
|
||||
output:
|
||||
|
||||
$ node wshuffle.js
|
||||
[ 'b', 'a', 'c', 'd', 'e' ]
|
||||
|
||||
weighted sample
|
||||
---------------
|
||||
|
||||
wpick.js:
|
||||
|
||||
var deck = require('deck');
|
||||
var x = deck.pick({
|
||||
a : 10,
|
||||
b : 8,
|
||||
c : 2,
|
||||
d : 1,
|
||||
e : 1,
|
||||
});
|
||||
console.log(x);
|
||||
|
||||
output:
|
||||
|
||||
$ node wpick.js
|
||||
a
|
||||
|
||||
methods
|
||||
=======
|
||||
|
||||
Note: both `deck(xs).pick()` and `deck.pick(xs)` styles work.
|
||||
|
||||
deck.shuffle(xs)
|
||||
----------------
|
||||
|
||||
Return a new shuffled `xs` without mutating the original.
|
||||
|
||||
If `xs` is an Array, return a new shuffled Array based on a unifrom
|
||||
distribution.
|
||||
|
||||
Otherwise if `xs` is an object, return a new shuffled Array of `xs`'s visible
|
||||
keys based on the value weights of `xs`.
|
||||
|
||||
deck.pick(xs)
|
||||
-------------
|
||||
|
||||
Sample `xs` without mutating `xs`.
|
||||
|
||||
If `xs` is an Array, return a random element from `xs` with a uniform
|
||||
distribution.
|
||||
|
||||
Otherwise if `xs` is an object, return a random key from `xs` biased by its
|
||||
normalized value.
|
||||
|
||||
deck.normalize(xs)
|
||||
------------------
|
||||
|
||||
Return a new `xs` object where the values have been divided by the sum of all
|
||||
the values such that the sum of all the values in the return object is 1.
|
||||
|
||||
If any weights are `< 0` normalize throws an error.
|
||||
|
||||
installation
|
||||
============
|
||||
|
||||
With [npm](http://npmjs.org):
|
||||
|
||||
npm install deck
|
10
node_modules/deck/bench/shuffle.js
generated
vendored
Normal file
10
node_modules/deck/bench/shuffle.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
var shuffle = require('../').shuffle;
|
||||
var xs = [];
|
||||
for (var i = 0; i < 1e5; i++) {
|
||||
xs.push(Math.floor(Math.random() * 1e3));
|
||||
}
|
||||
|
||||
var t0 = Date.now();
|
||||
shuffle(xs);
|
||||
var elapsed = Date.now() - t0;
|
||||
console.log(elapsed);
|
3
node_modules/deck/example/pick.js
generated
vendored
Normal file
3
node_modules/deck/example/pick.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
var deck = require('deck');
|
||||
var x = deck.pick([ 1, 2, 3, 4 ]);
|
||||
console.log(x);
|
3
node_modules/deck/example/shuffle.js
generated
vendored
Normal file
3
node_modules/deck/example/shuffle.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
var deck = require('deck');
|
||||
var xs = deck.shuffle([ 1, 2, 3, 4 ]);
|
||||
console.log(xs);
|
9
node_modules/deck/example/wpick.js
generated
vendored
Normal file
9
node_modules/deck/example/wpick.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
var deck = require('deck');
|
||||
var x = deck.pick({
|
||||
a : 10,
|
||||
b : 8,
|
||||
c : 2,
|
||||
d : 1,
|
||||
e : 1,
|
||||
});
|
||||
console.log(x);
|
9
node_modules/deck/example/wshuffle.js
generated
vendored
Normal file
9
node_modules/deck/example/wshuffle.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
var deck = require('deck');
|
||||
var xs = deck.shuffle({
|
||||
a : 10,
|
||||
b : 8,
|
||||
c : 2,
|
||||
d : 1,
|
||||
e : 1,
|
||||
});
|
||||
console.log(xs);
|
99
node_modules/deck/index.js
generated
vendored
Normal file
99
node_modules/deck/index.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
var exports = module.exports = function (xs) {
|
||||
if (typeof xs !== 'object') { // of which Arrays are
|
||||
throw new TypeError('Must be an Array or an object');
|
||||
}
|
||||
|
||||
return Object.keys(exports).reduce(function (acc, name) {
|
||||
acc[name] = exports[name].bind(null, xs);
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
||||
exports.shuffle = function (xs) {
|
||||
if (Array.isArray(xs)) {
|
||||
// uniform shuffle
|
||||
var res = xs.slice();
|
||||
for (var i = res.length - 1; i >= 0; i--) {
|
||||
var n = Math.floor(Math.random() * i);
|
||||
var t = res[i];
|
||||
res[i] = res[n];
|
||||
res[n] = t;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
else if (typeof xs === 'object') {
|
||||
// weighted shuffle
|
||||
var weights = Object.keys(xs).reduce(function (acc, key) {
|
||||
acc[key] = xs[key];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
var ret = [];
|
||||
|
||||
while (Object.keys(weights).length > 0) {
|
||||
var key = exports.pick(weights);
|
||||
delete weights[key];
|
||||
ret.push(key);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
throw new TypeError('Must be an Array or an object');
|
||||
}
|
||||
};
|
||||
|
||||
exports.pick = function (xs) {
|
||||
if (Array.isArray(xs)) {
|
||||
// uniform sample
|
||||
return xs[Math.floor(Math.random() * xs.length)];
|
||||
}
|
||||
else if (typeof xs === 'object') {
|
||||
// weighted sample
|
||||
var weights = exports.normalize(xs);
|
||||
if (!weights) return undefined;
|
||||
|
||||
var n = Math.random();
|
||||
var threshold = 0;
|
||||
var keys = Object.keys(weights);
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
threshold += weights[keys[i]];
|
||||
if (n < threshold) return keys[i];
|
||||
}
|
||||
throw new Error('Exceeded threshold. Something is very wrong.');
|
||||
}
|
||||
else {
|
||||
throw new TypeError('Must be an Array or an object');
|
||||
}
|
||||
};
|
||||
|
||||
exports.normalize = function (weights) {
|
||||
if (typeof weights !== 'object' || Array.isArray(weights)) {
|
||||
throw 'Not an object'
|
||||
}
|
||||
|
||||
var keys = Object.keys(weights);
|
||||
if (keys.length === 0) return undefined;
|
||||
|
||||
var total = keys.reduce(function (sum, key) {
|
||||
var x = weights[key];
|
||||
if (x < 0) {
|
||||
throw new Error('Negative weight encountered at key ' + key);
|
||||
}
|
||||
else if (typeof x !== 'number') {
|
||||
throw new TypeError('Number expected, got ' + typeof x);
|
||||
}
|
||||
else {
|
||||
return sum + x;
|
||||
}
|
||||
}, 0);
|
||||
|
||||
return total === 1
|
||||
? weights
|
||||
: keys.reduce(function (acc, key) {
|
||||
acc[key] = weights[key] / total;
|
||||
return acc;
|
||||
}, {})
|
||||
;
|
||||
};
|
67
node_modules/deck/package.json
generated
vendored
Normal file
67
node_modules/deck/package.json
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"_from": "deck@>=0.0.3",
|
||||
"_id": "deck@0.0.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha1-1NidRguoHuggsEoFp9Dc5k2Lcwo=",
|
||||
"_location": "/deck",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "deck@>=0.0.3",
|
||||
"name": "deck",
|
||||
"escapedName": "deck",
|
||||
"rawSpec": ">=0.0.3",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": ">=0.0.3"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/markov"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/deck/-/deck-0.0.4.tgz",
|
||||
"_shasum": "d4d89d460ba81ee820b04a05a7d0dce64d8b730a",
|
||||
"_spec": "deck@>=0.0.3",
|
||||
"_where": "/home/dabbott/dev/chainy/node_modules/markov",
|
||||
"author": {
|
||||
"name": "James Halliday",
|
||||
"email": "mail@substack.net",
|
||||
"url": "http://substack.net"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/substack/node-deck/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "Uniform and weighted shuffling and sampling",
|
||||
"devDependencies": {
|
||||
"expresso": ">=0.7.0"
|
||||
},
|
||||
"directories": {
|
||||
"lib": ".",
|
||||
"example": "./example"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
},
|
||||
"homepage": "https://github.com/substack/node-deck#readme",
|
||||
"keywords": [
|
||||
"shuffle",
|
||||
"sample",
|
||||
"normalize",
|
||||
"pick",
|
||||
"choose",
|
||||
"cards",
|
||||
"weights"
|
||||
],
|
||||
"license": "MIT/X11",
|
||||
"main": "./index.js",
|
||||
"name": "deck",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/substack/node-deck.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "expresso"
|
||||
},
|
||||
"version": "0.0.4"
|
||||
}
|
20
node_modules/deck/test/normalize.js
generated
vendored
Normal file
20
node_modules/deck/test/normalize.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
var deck = require('deck');
|
||||
var assert = require('assert');
|
||||
var eql = assert.deepEqual;
|
||||
|
||||
exports.normalize = function () {
|
||||
eql(
|
||||
deck.normalize({ a : 1, b : 3, c : 4 }),
|
||||
{ a : 0.125, b : 0.375, c : 0.5 }
|
||||
);
|
||||
|
||||
var t = 0.1 + 0.2 + 0.05;
|
||||
eql(
|
||||
deck.normalize({ a : 0.1, b : 0.2, c : 0.05 }),
|
||||
{ a : 0.1 / t, b : 0.2 / t, c : 0.05 / t }
|
||||
);
|
||||
|
||||
assert.throws(function () {
|
||||
deck.normalize({ a : 0.1, b : 0.2, c : [] });
|
||||
});
|
||||
};
|
69
node_modules/deck/test/pick.js
generated
vendored
Normal file
69
node_modules/deck/test/pick.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
var deck = require('deck');
|
||||
var assert = require('assert');
|
||||
var eql = assert.deepEqual;
|
||||
|
||||
function picker (fn) {
|
||||
var xs = [0,1,2,3,4,5,6,7,8,9];
|
||||
var counts = {};
|
||||
var loops = 50000;
|
||||
|
||||
for (var i = 0; i < loops; i++) {
|
||||
var x = fn(xs);
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
}
|
||||
eql(Object.keys(counts).sort(), xs);
|
||||
eql(xs, [0,1,2,3,4,5,6,7,8,9], 'shuffle mutated its argument');
|
||||
|
||||
xs.forEach(function (x) {
|
||||
assert.ok(
|
||||
counts[x] * xs.length >= loops * 0.95
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
counts[x] * xs.length <= loops * 1.05
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
exports.pick = function () {
|
||||
picker(deck.pick);
|
||||
};
|
||||
|
||||
exports.pickObj = function () {
|
||||
picker(function (xs) {
|
||||
return deck(xs).pick()
|
||||
});
|
||||
};
|
||||
|
||||
exports.weightedPick = function () {
|
||||
var counts = {};
|
||||
var weights = { a : 2, b : 10, c : 1 };
|
||||
var total = 2 + 10 + 1;
|
||||
var loops = 50000;
|
||||
|
||||
for (var i = 0; i < loops; i++) {
|
||||
var x = deck.pick(weights);
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
}
|
||||
|
||||
eql(Object.keys(counts).sort(), [ 'a', 'b', 'c' ]);
|
||||
|
||||
Object.keys(weights).forEach(function (key) {
|
||||
assert.ok(
|
||||
counts[key] / weights[key] * total >= loops * 0.95
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
counts[key] / weights[key] * total <= loops * 1.05
|
||||
);
|
||||
});
|
||||
|
||||
assert.throws(function () {
|
||||
deck.pick({ a : 5, b : 2, c : /moo/ });
|
||||
});
|
||||
};
|
||||
|
||||
exports.pickEmpty = function () {
|
||||
assert.ok(deck.pick([]) === undefined);
|
||||
assert.ok(deck.pick({}) === undefined);
|
||||
};
|
71
node_modules/deck/test/shuffle.js
generated
vendored
Normal file
71
node_modules/deck/test/shuffle.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
var deck = require('deck');
|
||||
var assert = require('assert');
|
||||
|
||||
function shuffler (fn) {
|
||||
var xs = [0,1,2,3,4,5,6,7,8,9];
|
||||
var xs_ = fn(xs);
|
||||
assert.eql(xs, [0,1,2,3,4,5,6,7,8,9], 'shuffle mutated its argument');
|
||||
assert.eql(xs.length, 10);
|
||||
assert.ok(xs.every(function (x) {
|
||||
return xs_.indexOf(x) >= 0
|
||||
}));
|
||||
}
|
||||
|
||||
exports.shuffle = function () {
|
||||
shuffler(deck.shuffle);
|
||||
};
|
||||
|
||||
exports.quick = function () {
|
||||
var xs = [];
|
||||
for (var i = 0; i < 1e5; i++) xs.push(Math.random());
|
||||
|
||||
var t0 = Date.now();
|
||||
var xs_ = deck.shuffle(xs);
|
||||
var elapsed = Date.now() - t0;
|
||||
assert.ok(elapsed < 200);
|
||||
assert.equal(xs.length, 1e5);
|
||||
};
|
||||
|
||||
exports.shuffleObj = function () {
|
||||
shuffler(function (xs) {
|
||||
return deck(xs).shuffle()
|
||||
});
|
||||
};
|
||||
|
||||
exports.weightedShuffle = function () {
|
||||
assert.eql(deck.shuffle({ a : 1000, b : 0.01 }), [ 'a', 'b' ]);
|
||||
|
||||
var weights = { a : 3, b : 1, c : 10 };
|
||||
var total = 3 + 1 + 10;
|
||||
var loops = 5000;
|
||||
|
||||
var counts = {};
|
||||
for (var i = 0; i < loops; i++) {
|
||||
var x = deck.shuffle(weights).join('');
|
||||
counts[x] = (counts[x] || 0) + 1;
|
||||
}
|
||||
|
||||
function margins (key) {
|
||||
var keys = key.split('');
|
||||
var expected = key.split('').reduce(function (p, x) {
|
||||
var p_ = p * weights[x] / keys.reduce(function (acc, k) {
|
||||
return acc + weights[k];
|
||||
}, 0);
|
||||
keys.shift();
|
||||
return p_;
|
||||
}, loops);
|
||||
assert.ok(counts[key] >= 0.95 * expected);
|
||||
assert.ok(counts[key] <= 1.05 * expected);
|
||||
}
|
||||
|
||||
Object.keys(counts).every(margins);
|
||||
|
||||
assert.throws(function () {
|
||||
deck.shuffle({ a : 1, b : 'x', c : 5 });
|
||||
});
|
||||
};
|
||||
|
||||
exports.shuffleEmpty = function () {
|
||||
assert.eql(deck.shuffle([]), []);
|
||||
assert.eql(deck.shuffle({}), []);
|
||||
};
|
Reference in New Issue
Block a user