This page invites you to experiment with various pseudo-random number generators crafted in Python and watch as their outputs come to life in a dynamic histogram.
As you dive into this adventure, you’ll discover that a well-crafted generator will gracefully balance the bars over time, creating a harmonious distribution. On the other hand, a less effective generator might reveal quirky patterns, with some bars mysteriously absent.
Of course, this is not a statistical test; it is just a visual animation that demonstrates what Marimo Islands can do in your browser!
import%20marimo%20as%20mo%0A%0Acode%20%3D%20mo.ui.code_editor(%22%22%22def%20lcg(seed%2C%20a%2C%20c%2C%20m)%3A%0A%20%20%20%20def%20_aux()%3A%0A%20%20%20%20%20%20%20%20nonlocal%20seed%0A%20%20%20%20%20%20%20%20seed%20%3D%20(a%20*%20seed%20%2B%20c)%20%25%20m%0A%20%20%20%20%20%20%20%20return%20seed%20%2F%20m%0A%0A%20%20%20%20return%20_aux%0A%0A%0Adef%20mulberry32(seed)%3A%0A%20%20%20%20seed%20%26%3D%200xFFFFFFFF%0A%0A%20%20%20%20def%20_aux()%20-%3E%20float%3A%0A%20%20%20%20%20%20%20%20nonlocal%20seed%0A%20%20%20%20%20%20%20%20seed%20%3D%20(seed%20%2B%200x6D2B79F5)%20%26%200xFFFFFFFF%0A%20%20%20%20%20%20%20%20t%20%3D%20seed%0A%20%20%20%20%20%20%20%20t%20%3D%20((t%20%5E%20(t%20%3E%3E%2015))%20*%20(t%20%7C%201))%20%26%200xFFFFFFFF%0A%20%20%20%20%20%20%20%20t%20%5E%3D%20(t%20%2B%20((t%20%5E%20(t%20%3E%3E%207))%20*%20(t%20%7C%2061)%20%26%200xFFFFFFFF))%20%26%200xFFFFFFFF%0A%20%20%20%20%20%20%20%20return%20((t%20%5E%20(t%20%3E%3E%2014))%20%26%200xFFFFFFFF)%20%2F%204294967296.0%0A%0A%20%20%20%20return%20_aux%0A%0A%0A%23%20Not%20really%20uniform%2C%20bad%20selection%20of%20params...%0Arng%20%3D%20lcg(seed%3D3%2C%20a%3D15%2C%20c%3D12%2C%20m%3D2**8)%0A%23%20Better%20params%20as%20suggested%20by%20numerical%20recipies%3A%0A%23rng%20%3D%20lcg(seed%3D1%2C%20a%3D1664525%2C%20c%3D1013904223%2C%20m%3D2**32)%0A%23%20You%20can%20also%20try%20Mulberry32%3A%0A%23rng%20%3D%20mulberry32(124)%22%22%22%2C%20theme%3D%22dark%22)%0A%0Acode
exec(code.value%2C%20globals())%0Amo.md(f%22The%20first%20random%20number%20generated%20by%20your%20function%20is%20%7Brng()%7D%22)
import%20anywidget%0Aimport%20traitlets%0A%0Aclass%20StreamingHistogram(anywidget.AnyWidget)%3A%0A%20%20%20%20%22%22%22%0A%20%20%20%20Histograma%20en%20tiempo%20real%20de%200%E2%80%931%20usando%20la%20funci%C3%B3n%20global%20%60rng()%60.%0A%20%20%20%20%22%22%22%0A%20%20%20%20_esm%20%3D%20r%22%22%22%0A%20%20%20%20import%20*%20as%20d3%20from%20%22https%3A%2F%2Fesm.sh%2Fd3%407%22%3B%0A%20%20%20%20export%20default%20%7B%0A%20%20%20%20%20%20render(%7B%20model%2C%20el%20%7D)%20%7B%0A%20%20%20%20%20%20%20%20const%20bins%20%3D%20model.get('bins')%3B%0A%20%20%20%20%20%20%20%20const%20margin%20%3D%20%7B%20top%3A%2020%2C%20right%3A%2020%2C%20bottom%3A%2030%2C%20left%3A%2040%20%7D%3B%0A%20%20%20%20%20%20%20%20const%20width%20%20%3D%20(model.get('width')%20%20%7C%7C%20600)%20-%20margin.left%20-%20margin.right%3B%0A%20%20%20%20%20%20%20%20const%20height%20%3D%20(model.get('height')%20%7C%7C%20350)%20-%20margin.top%20%20-%20margin.bottom%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20crea%20SVG%0A%20%20%20%20%20%20%20%20const%20svg%20%3D%20d3.select(el).html('')%0A%20%20%20%20%20%20%20%20%20%20.append('svg')%0A%20%20%20%20%20%20%20%20%20%20%20%20.attr('width'%2C%20%20width%20%20%2B%20margin.left%20%2B%20margin.right)%0A%20%20%20%20%20%20%20%20%20%20%20%20.attr('height'%2C%20height%20%2B%20margin.top%20%20%2B%20margin.bottom)%0A%20%20%20%20%20%20%20%20%20%20.append('g')%0A%20%20%20%20%20%20%20%20%20%20%20%20.attr('transform'%2C%20%60translate(%24%7Bmargin.left%7D%2C%24%7Bmargin.top%7D)%60)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20funci%C3%B3n%20para%20dibujar%20con%20los%20datos%20actuales%0A%20%20%20%20%20%20%20%20function%20draw(data)%20%7B%0A%20%20%20%20%20%20%20%20%20%20const%20x%20%3D%20d3.scaleLinear()%0A%20%20%20%20%20%20%20%20%20%20%20%20.domain(%5B0%2C%201%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20.range(%5B0%2C%20width%5D)%3B%0A%20%20%20%20%20%20%20%20%20%20const%20y%20%3D%20d3.scaleLinear()%0A%20%20%20%20%20%20%20%20%20%20%20%20.domain(%5B0%2C%20Math.max(1%2C%20d3.max(data))%5D).nice()%20%2F%2F%20Asegura%20que%20el%20dominio%20comience%20en%200%0A%20%20%20%20%20%20%20%20%20%20%20%20.range(%5Bheight%2C%200%5D)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20const%20barWidth%20%3D%20width%20%2F%20bins%20*%200.99%3B%20%2F%2F%2090%25%20del%20espacio%20para%20dejar%20un%20gap%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20BARRAS%0A%20%20%20%20%20%20%20%20%20%20svg.selectAll('rect')%0A%20%20%20%20%20%20%20%20%20%20%20%20.data(data)%0A%20%20%20%20%20%20%20%20%20%20%20%20.join('rect')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('x'%2C%20%20%20(_d%2Ci)%20%3D%3E%20x(i%20%2F%20bins))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('width'%2C%20barWidth)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('y'%2C%20%20%20d%20%3D%3E%20y(d))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('height'%2C%20d%20%3D%3E%20height%20-%20y(d))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('fill'%2C%20'red')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('stroke'%2C%20'black')%20%2F%2F%20borde%20negro%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('stroke-width'%2C%200.5)%3B%20%2F%2F%20grosor%20del%20borde%0A%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20EJE%20X%0A%20%20%20%20%20%20%20%20%20%20svg.selectAll('.x-axis')%0A%20%20%20%20%20%20%20%20%20%20%20%20.data(%5Bnull%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20.join('g')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('class'%2C'x-axis')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('transform'%2C%20%60translate(0%2C%24%7Bheight%7D)%60)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.call(d3.axisBottom(x).ticks(bins))%3B%0A%20%20%20%20%20%20%20%20%20%20%2F%2F%20EJE%20Y%0A%20%20%20%20%20%20%20%20%20%20svg.selectAll('.y-axis')%0A%20%20%20%20%20%20%20%20%20%20%20%20.data(%5Bnull%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20.join('g')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.attr('class'%2C'y-axis')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20.call(d3.axisLeft(y).ticks(5))%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20al%20cambiar%20%60data%60%2C%20re-dibuja%0A%20%20%20%20%20%20%20%20model.on('change%3Adata'%2C%20()%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20draw(model.get('data'))%3B%0A%20%20%20%20%20%20%20%20%7D%2C%20this)%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20dibujado%20inicial%0A%20%20%20%20%20%20%20%20draw(model.get('data'))%3B%0A%0A%20%20%20%20%20%20%20%20%2F%2F%20inicia%20el%20tick%20loop%20si%20%60running%60%0A%20%20%20%20%20%20%20%20let%20timer%20%3D%20null%3B%0A%20%20%20%20%20%20%20%20function%20start()%20%7B%0A%20%20%20%20%20%20%20%20%20%20if%20(timer)%20return%3B%0A%20%20%20%20%20%20%20%20%20%20timer%20%3D%20setInterval(()%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20model.send(%7B%20event%3A%20'tick'%20%7D)%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%2C%20model.get('interval')%20*%201000)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20function%20stop()%20%7B%0A%20%20%20%20%20%20%20%20%20%20clearInterval(timer)%3B%0A%20%20%20%20%20%20%20%20%20%20timer%20%3D%20null%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%2F%2F%20arranca%2Fparara%20seg%C3%BAn%20%60running%60%0A%20%20%20%20%20%20%20%20model.on('change%3Arunning'%2C%20()%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20model.get('running')%20%3F%20start()%20%3A%20stop()%3B%0A%20%20%20%20%20%20%20%20%7D%2C%20this)%3B%0A%20%20%20%20%20%20%20%20if%20(model.get('running'))%20start()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20%22%22%22%0A%0A%20%20%20%20bins%20%20%20%20%20%3D%20traitlets.Int(10).tag(sync%3DTrue)%0A%20%20%20%20interval%20%3D%20traitlets.Float(0.15).tag(sync%3DTrue)%0A%20%20%20%20running%20%20%3D%20traitlets.Bool(True).tag(sync%3DTrue)%0A%20%20%20%20data%20%20%20%20%20%3D%20traitlets.List(traitlets.Int()%2C%20default_value%3D%5B0%5D*10).tag(sync%3DTrue)%0A%20%20%20%20width%20%20%20%20%3D%20traitlets.Int(500).tag(sync%3DTrue)%0A%20%20%20%20height%20%20%20%3D%20traitlets.Int(250).tag(sync%3DTrue)%0A%0A%20%20%20%20def%20__init__(self%2C%20**kwargs)%3A%0A%20%20%20%20%20%20%20%20super().__init__(**kwargs)%0A%20%20%20%20%20%20%20%20self.data%20%3D%20%5B0%5D%20*%20self.bins%0A%20%20%20%20%20%20%20%20self.on_msg(self._handle_tick)%0A%0A%20%20%20%20def%20_handle_tick(self%2C%20_%2C%20content%2C%20buffers)%3A%0A%20%20%20%20%20%20%20%20if%20content.get('event')%20%3D%3D%20'tick'%20and%20self.running%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20idx%20%3D%20int(rng()%20*%20self.bins)%0A%20%20%20%20%20%20%20%20%20%20%20%20lst%20%3D%20list(self.data)%0A%20%20%20%20%20%20%20%20%20%20%20%20lst%5Bidx%5D%20%2B%3D%201%0A%20%20%20%20%20%20%20%20%20%20%20%20self.data%20%3D%20lst
hist%20%3D%20StreamingHistogram()%0Ahist
reset_button%20%3D%20mo.ui.button(label%3D%22Reset%20Histogram%22)%0Areset_button
reset_button.value%0Ahist.data%20%3D%20%5B0%5D%20*%20hist.bins