Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..

README.md

Weighted Random

Weighted Random

What is "Weighted Random"

Let's say you have a list of items. Item could be anything. For example, we may have a list of fruits and vegetables that you like to eat: [ '🍌', '🍎', '🥕' ].

The list of weights represent the weight (or probability, or importance) of each item. Weights are numbers. For example, the weights like [3, 7, 1] would say that:

  • you would like to eat 🍎 apples more often (7 out of 3 + 7 + 1 = 11 times),
  • then you would like to eat bananas 🍌 less often (only 3 out of 11 times),
  • and the carrots 🥕 you really don't like (want to eat it only 1 out of 11 times).

If we speak in terms of probabilities than the weights list might be an array of floats that sum up to 1 (i.e. [0.1, 0.5, 0.2, 0.2]).

The Weighted Random in this case will be the function that will randomly return you the item from the list, and it will take each item's weight into account, so that items with the higher weight will be picked more often.

Example of the function interface:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];functionweightedRandom(items,weights){// implementation goes here ...}constnextSnackToEat=weightedRandom(items,weights);// Could be '🍎'

Applications of Weighted Random

The Algorithm

The straightforward approach would be to:

  1. Repeat each item in the list according to its weight.
  2. Pick the random item from the list.

For example in our case with fruits and vegetables we could generate the following list of size 3 + 7 + 1 = 11:

constitems=['🍌','🍎','🥕'];constweights=[3,7,1];// Repeating the items based on weights.constweightedItems=['🍌','🍌','🍌','🍎','🍎','🍎','🍎','🍎','🍎','🍎','🥕',];// And now just pick the random item from weightedItems array.

However, as you may see, this approach may require a lot of memory, in case if we have a lot of items to repeat in weightedItems list. Think of it as if you would need to repeat a string like "some-random-string" (18 bytes) a ten million times. You will need to allocate around 180Mb of additional memory space just for this array.

The more efficient approach would be to:

  1. Prepare the list of cumulative weights for each item (i.e. the cumulativeWeights list which will have the same number of elements as the original weights list). In our case it will look like this: cumulativeWeights = [3, 3 + 7, 3 + 7 + 1] = [3, 10, 11]
  2. Generate the random number randomNumber from 0 to the highest cumulative weight value. In our case the random number will be in a range of [0..11]. Let's say that we have randomNumber = 8.
  3. Go through the cumulativeWeights list from left to right and pick the first element which is higher or equal to the randomNumber. The index of such element we will use to pick the item from the items array.

The idea behind this approach is that the higher weights will "occupy" more numeric space. Therefore, there is a higher chance that the random number will fall into the "higher weight numeric bucket".

constweights=[3,7,1];constcumulativeWeights=[3,10,11];// In a pseudo-representation we may think about the cumulativeWeights array like this.constpseudoCumulativeWeights=[1,2,3,// <-- [3] numbers4,5,6,7,8,9,10,// <-- [7] numbers11,// <-- [1] number];

Here is an example of how the weightedRandom function might be implemented:

/** * Picks the random item based on its weight. * The items with higher weight will be picked more often (with a higher probability). * * For example: * - items = ['banana', 'orange', 'apple'] * - weights = [0, 0.2, 0.8] * - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return * 'orange' and it will never return 'banana' (because probability of picking the banana is 0%) * * @param {any[]} items * @param {number[]} weights * @returns {{item: any, index: number}} */exportdefaultfunctionweightedRandom(items,weights){if(items.length!==weights.length){thrownewError('Items and weights must be of the same size');}if(!items.length){thrownewError('Items must not be empty');}// Preparing the cumulative weights array.// For example:// - weights = [1, 4, 3]// - cumulativeWeights = [1, 5, 8]constcumulativeWeights=[];for(leti=0;i<weights.length;i+=1){cumulativeWeights[i]=weights[i]+(cumulativeWeights[i-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]constmaxCumulativeWeight=cumulativeWeights[cumulativeWeights.length-1];constrandomNumber=maxCumulativeWeight*Math.random();// Picking the random item based on its weight.// The items with higher weight will be picked more often.for(letitemIndex=0;itemIndex<items.length;itemIndex+=1){if(cumulativeWeights[itemIndex]>=randomNumber){return{item: items[itemIndex],index: itemIndex,};}}}

Implementation