Skip to content

Instantly share code, notes, and snippets.

@Krewn
Last active March 27, 2025 02:28
Show Gist options
  • Select an option

  • Save Krewn/f9fb2e7860126c029fde6de53ea7b615 to your computer and use it in GitHub Desktop.

Select an option

Save Krewn/f9fb2e7860126c029fde6de53ea7b615 to your computer and use it in GitHub Desktop.
A questionably stable implementation of random selection by urandom demonstrated with some bingo pulls.
from os import urandom
from math import *
import hashlib
import time
class ___:
pass
_dir = dir(___)
def printSelf(x):
for _ in set(dir(x))-set(_dir):
print(_,":",f'{getattr(x,_)}')
print()
class randomIndexer:
def __init__(self,r = urandom,i = 9001):
self.r = r
self.seti(i)
def seti(self,i):
self.i = i
self.nBytes = ceil(log(i,256))
self.nBytes = self.nBytes if self.nBytes else 1
self.extraBits = 8*self.nBytes-ceil(log(i,2))
def next(self):
randBytes = self.r(self.nBytes)
first = bin(randBytes[0])[self.extraBits+2:]
if len(first) == 0:
first = "0"
randBytes = int.to_bytes(int(first,2))+randBytes[1:]
ans = int.from_bytes(randBytes)
if ans < self.i:
return ans
return self.next()
import itertools
from itertools import product
class bingo:
def __init__(self,balls = ["".join([str(__) for __ in _]) for _ in product([chr(_) for _ in range(48,58)],[chr(_) for _ in range(65,91)])], head = b'ingo'):
self.deck = balls
self.counts = {k:0 for k in self.deck}
self.hand = []
self.seq = []
self.ri = randomIndexer(i=len(self.deck))
def printSeq(self):
return "-".join(self.seq)
def next(self):
#printSelf(self.ri)
i = self.ri.next()
self.hand.append(self.deck[i])
self.counts[self.hand[-1]] += 1
self.seq.append(self.hand[-1])
del self.deck[i]
if len(self.deck)==0:
last = self.seq[-1]
self.restart(announce = True)
return last
self.ri.seti(self.ri.i-1)
return self.seq[-1]
def leadPool(self):
m = max(self.counts.values())
return [x for x in self.counts.keys() if self.counts[x] == m]
def tailPool(self):
m = min(self.counts.values())
return [x for x in self.counts.keys() if self.counts[x] == m]
def restart(self,announce = False):
print("\n"+" ".join(self.seq),self.deck,end=" -- refill\n\n")
self.deck = self.deck+self.hand
self.ri.seti(len(self.deck))
self.hand = []
self.seq = []
if announce:
self.printSeq()
#print(f"Lead: {' '.join(self.leadPool())}")
print("\n". join([f"{str(x).center(len(str(max(self.counts.values()))))} : {' '.join([k for k,v in self.counts.items() if v == x])}" for x in range(max(self.counts.values()),min(self.counts.values())-1,-1) if x in self.counts.values()])+"\n")
#print(f"Tail: {' '.join(self.tailPool())}")
b = bingo(balls = ["-".join([str(__) for __ in _]) for _ in product([_ for _ in "BINGO"],[chr(_) for _ in range(48,55)])] )
while True:
for _ in range(5):
s = []
for __ in range(5):
s.append(b.next())
print(" ".join(s))
time.sleep(1)
b.restart()
time.sleep(2)
#print("-".join(["".join(b.next()) for _ in range(3)]))
"""
rx = randomIndexer()
buckets = {}
c = 0
while c<1000000:
x = rx.next()
try:
buckets[x]+=1
except KeyError:
buckets[x] = 1
c+=1
print(min(buckets.values()),max(buckets.values()))
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment