JSFiddle - React, Tailwind, and code Playground

Seedable Fisher-Yates Shuffle

by skibulk

HTML

<p><button id="toggleButton">Start/Stop</button></p>
<p>Last User ID: <span id="userCount"></span></p>
<p>Total Cards Generated: <span id="cardCount"></span></p>
<p>Memory Used (MBs): <span id="memoryCount"></span></p>
<p>Duplicate Cards: <span id="duplicateCount"></span></p>

CSS

body {
  background-color: white;
}

JavaScript

// SETUP -----------------------

// https://gist.github.com/josephrocca/44e4c0b63828cfc6d6155097b2efc113
class BigMap {
  constructor() {
    this._maps = [new Map()];
    this._perMapSizeLimit = 14000000;
    this.size = 0;
  }
  has(key) {
    for(let map of this._maps) {
      if(map.has(key)) return true;
    }
    return false;
  }
  get(key) {
    for(let map of this._maps) {
      if(map.has(key)) return map.get(key);
    }
    return undefined;
  }
  set(key, value) {
    for(let map of this._maps) {
      if(map.has(key)) {
        map.set(key, value);
        return this;
      }
    }
    let map = this._maps[this._maps.length-1];
    if(map.size > this._perMapSizeLimit) {
      map = new Map();
      this._maps.push(map);
    }
    map.set(key, value);
    this.size++;
    return this;
  }
}

// Seedable Fisher-Yates Shuffle
// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
function shuffle(str, seed) {
  // Copy source array (don't edit the original)
  str = [...str];
  
  // The seed cannot be 0
  seed += 1;
  
  // L = str Length
  // I = Source Index
  // J = Target Index
  // C = Source Character
  var l = str.length;
  var i, j, c;

  // Iterate Source Indices
  for (i = 0; i < l; i++) {

    // 1993 Park–Miller LCG
    // Period of 2^31-1 ~= 2.1 Billion
    // https://en.wikipedia.org/wiki/Lehmer_random_number_generator
    seed = seed * 48271 % 2147483647;
    
    // See TABLES OF LINEAR CONGRUENTIAL GENERATORS... PIERRE L’ECUYER
    // Period of 2^35-31 ~= 34.4 Billion
    // seed = (Math.imul(seed, 185852) + 1) % 34359738337
    
    j = Math.floor(seed / 2147483647 * l);
    
    // Swap source character with target character
    c = str[i];
    str[i] = str[j];
    str[j] = c;
  }

  return str.join("");
}

// Make Math.random secure - Requires Chrome or Firefox.
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
if (window.crypto.getRandomValues) {
  Math.random = function() {
    return...