Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 9x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 1x 1x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 1x 1x 1x | /**
* @src https://basarat.gitbook.io/algorithms/basics/tips#random-numbers
* "Generate a random number between min and max."
*
* The function uses the `Math.random()` function to generate a random number between 0 and 1. It then multiplies that
* number by the difference between `max` and `min` and adds `min` to it
* @param {number} min - The minimum value to return.
* @param {number} max - The maximum value of the random number.
* @returns A random number between the min and max values.
*/
export const random = (min: number, max: number): number => {
if (!window.crypto) {
// eslint-disable-next-line no-bitwise
return ~~(Math.random() * (max - min) + min);
}
// eslint-disable-next-line compat/compat
const randomBuffer = new Uint32Array(1);
window.crypto.getRandomValues(randomBuffer);
const randomNumber = randomBuffer[0] / (0xffffffff + 1);
const minimum = Math.ceil(min);
const maximum = Math.floor(max);
return Math.floor(randomNumber * (maximum - minimum + 1)) + minimum;
};
/**
* @src https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/statistics/weighted-random/weightedRandom.js
* "Given an array of items and an array of weights, pick one item randomly based on the weights."
*
* The function is generic, so it can be used with any type of items
* @param {Item[]} items - The array of items to pick from.
* @param {number[]} weights - An array of numbers that represent the weight of each item.
* @returns Nothing.
*/
export const weightedRandom = <Item>(items: Item[], weights: number[]): Item | undefined => {
if (items.length !== weights.length) {
throw new Error("Items and weights must be of the same size");
}
if (!items.length) {
throw new Error("Items must not be empty");
}
// Preparing the cumulative weights array.
// For example:
// - weights = [1, 4, 3]
// - cumulativeWeights = [1, 5, 8]
const cumulativeWeights: number[] = [];
weights.forEach((weight, index) => {
// eslint-disable-next-line security/detect-object-injection
cumulativeWeights[index] = weight + (cumulativeWeights[index - 1] || 0);
});
// Getting the random number in a range of [0...sum(weights)]
// For example:
// - weights = [1, 4, 3]
// - maxCumulativeWeight = 8
// - range for the random number is [0...8]
const maxCumulativeWeight = cumulativeWeights[cumulativeWeights.length - 1];
const randomNumber = random(0, maxCumulativeWeight);
// Picking the random item based on its weight.
// The items with higher weight will be picked more often.
return items
.filter((_item, index) => {
// console.log(item);
// eslint-disable-next-line security/detect-object-injection
return cumulativeWeights[index] >= randomNumber;
})
.shift();
};
|