Skip to content

Instantly share code, notes, and snippets.

@diegovgsilva95
Created January 27, 2025 10:53
Show Gist options
  • Select an option

  • Save diegovgsilva95/1ea8e98eb20094ccbe123aace8ed2ea6 to your computer and use it in GitHub Desktop.

Select an option

Save diegovgsilva95/1ea8e98eb20094ccbe123aace8ed2ea6 to your computer and use it in GitHub Desktop.
JS - Playing with randomness: mapping randomness unto itself and ranking the "best" surviving sequence

Purpose

Actually, none (do things really need to have a purpose?)... Just another tinkering with randomness.

What it Currently Does/Behaves

  1. Generates a list of random L numbers (currently 100 numbers).
  2. Maps the current list so every number (expectedly 0 <= n <= 1) becomes an index i (i = round(n × L)) pointing to the ith number in the current list.
  3. Calculates the current diversity (i.e., how many unique numbers survived from the last iteration).
  4. If diversity converges to less than 100 after a couple of runs, goes back to the step 1.
  5. If diversity converges to exactly 100 after a couple of runs, prints "Got the best of all!" and exits the loop.
  6. If diversity hasn't converged yet, goes back to the step 2.

Expected Results

So far, it'll converge... but if the numbers are truly random, maybe there's a tiny possibility of a sequence whose diversity isn't destroyed by the iteration too much (i.e., the numbers will certainly switch positions, perhaps some of the numbers would disappear, but they'd end in an evenly distributed sequence spaced by something close to 1/N).

So far, the best I got was a random sequence which ended up with diversity = 38 (i.e., only 38 out of the 100 initial numbers "survived" the iterations).

import {randomBytes} from "crypto"
import {stdout} from "process"
import {log} from "console"
const sleep = ms => new Promise(r => setTimeout(r, ms))
const clear = _ => stdout.write("\x1b[H\x1b[2J\x1b[3J")
clear()
const RandomnessThingy = class {
static instance = null
static getInstance(){
if(!RandomnessThingy.instance)
RandomnessThingy.instance = new RandomnessThingy()
return RandomnessThingy.instance
}
maxBestRuns = 10
bestRuns = [] // Perhaps "best" actually means "worse entropy"?
randomAmt = 100
// TODO: add feed from TRNG (from my webcam-entropy)
randomFns = {
crypto: () => [...Float32Array.from(new Uint16Array(randomBytes(2*this.randomAmt).buffer)).map(x=>x/65536)],
pseudo: () => Array.from(Array(this.randomAmt), _ => Math.random()),
sequential: (n = Math.random()) => Array.from(Array(this.randomAmt), (_,i) => Math.abs(Math.sin(Math.PI * 2 * (i+n) / this.randomAmt))), //1-i/(this.randomAmt-1)
}
// "Best" i could find is 38 out of 100 (using the crypto PRNG source).
randomFn = this.randomFns.crypto
constructor(){
this.currentArr = null
this.currentRandom = null
this.currentIterations = 0
this.currentDiversity = 0
this.currentDiversityHistory = []
}
saveIfBest(){
let {bestRuns, maxBestRuns, currentRandom, currentDiversityHistory, currentDiversity} = this
this.bestRuns = [...bestRuns, {
randomSeed: currentRandom,
diversityHistory: currentDiversityHistory
}].sort((a,b)=>b.diversityHistory.at(-1)-a.diversityHistory.at(-1)).slice(0,maxBestRuns)
// I should do a better sorting, considering the whole diversityHistory...
}
regen(){
this.currentRandom = this.randomFn()
this.currentArr = this.currentRandom
this.currentIterations = 0
this.currentDiversityHistory = []
this.calculateDiversity()
}
iterate(){
let arr = this.currentArr
this.currentArr = arr.map(val =>
arr[Math.round(val*(arr.length-1))]
)
}
calculateDiversity(){
this.currentDiversity = new Set(this.currentArr).size
this.currentDiversityHistory.push(this.currentDiversity)
}
printArr(arr){
let lines = [""]
let cols = stdout.columns
for(let num of arr){
let numStr = num.toFixed(12)+", "
if(lines.at(-1).length+numStr.length >= cols){
lines.push("")
}
lines[lines.length-1] += numStr
}
log(lines.join("\n"))
log("")
}
checkDiversity(){
const maxLastAmt = 3
const {currentDiversityHistory} = this
if(currentDiversityHistory.length <= maxLastAmt)
return true
if(currentDiversityHistory.at(-1) == 100)
return true
for(let i = 0; i < maxLastAmt; i++){
if(currentDiversityHistory.at(-1-i) != currentDiversityHistory.at(-2-i))
return true
}
return false
}
async main(){
this.regen()
while(1){
clear()
log("Current:")
this.printArr(this.currentArr)
log("Diversity history: ", this.currentDiversityHistory.join(", "))
log("=".repeat(stdout.columns))
log("Best runs:")
log(this.bestRuns.map(x=>x.diversityHistory).join("\n"))
log("=".repeat(stdout.columns))
if(this.bestRuns.length > 0){
log("Best random seq:")
this.printArr(this.bestRuns[0].randomSeed)
}
this.iterate()
this.calculateDiversity()
if(!this.checkDiversity()){
this.saveIfBest()
this.regen()
} else if(this.currentDiversityHistory.at(-1) == 100 && this.currentDiversityHistory.length > 3){
log("Got the best of all!")
break
}
await sleep(50)
}
}
}
RandomnessThingy.getInstance().main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment