<p>There are many ways to generate a random integer with a custom distribution (also known as a <em>discrete distribution</em>). The choice depends on many things, including the number of integers to choose from, the shape of the distribution, and whether the distribution will change over time.</p>
<p>One of the simplest ways to choose an integer with a custom weight function <code>f(x)</code> is the <em>rejection sampling</em> method. The following assumes that the highest possible value of <code>f</code> is <code>max</code> and each weight is 0 or greater. The time complexity for rejection sampling is constant on average, but depends greatly on the shape of the distribution and has a worst case of running forever. To choose an integer in [1, <code>k</code>] using rejection sampling:</p>
<ol>
<li>Choose a uniform random integer <code>i</code> in [1, <code>k</code>].</li>
<li>With probability <code>f(i)/max</code>, return <code>i</code>. Otherwise, go to step 1. (For example, if all the weights are integers greater than 0, choose a uniform random integer in [1, <code>max</code>] and if that number is <code>f(i)</code> or less, return <code>i</code>, or go to step 1 otherwise.)</li>
</ol>
<p>Other algorithms have an average sampling time that doesn't depend so greatly on the distribution (usually either constant or logarithmic), but often require you to precalculate the weights in a setup step and store them in a data structure. Some of them are also economical in terms of the number of random bits they use on average. Many of these algorithms were introduced after 2011, and they include—</p>
<ul>
<li>The Bringmann–Larsen succinct data structure (&quot;Succinct Sampling from Discrete Distributions&quot;, 2012),</li>
<li>Yunpeng Tang's multi-level search (&quot;An Empirical Study of Random Sampling Methods for Changing Discrete Distributions&quot;, 2019), and</li>
<li>the <a href="https://arxiv.org/abs/2003.03830v2" rel="nofollow noreferrer">Fast Loaded Dice Roller</a> (2020).</li>
</ul>
<p>Other algorithms include the <em>alias method</em> (already mentioned in your article), the Knuth–Yao algorithm, the MVN data structure, and more. See my section &quot;<a href="https://peteroupc.github.io/randomfunc.html#Weighted_Choice_With_Replacement" rel="nofollow noreferrer">Weighted Choice With Replacement</a>&quot; for a survey.</p>
Data structures for loaded dice?
<p>Suppose that I have an <em>n</em>-sided loaded die, where each side <em>k</em> has some probability <em>p</em><sub><em>k</em></sub> of coming up when I roll it. I’m curious if there is a good data structure for storing this information statically (i.e., for a fixed set of probabilities), so that I can efficiently simulate a random roll of the die.</p>
<p>Currently, I have an O(lg <em>n</em>) solution for this problem. The idea is to store a table of the cumulative probability of the first <em>k</em> sides for all <em>k</em>, then generate a random real number in the range [0, 1) and perform a binary search over the table to get the largest index whose cumulative value is no greater than the chosen value.</p>
<p>I rather like this solution, but it seems odd that the runtime doesn’t take the probabilities into account. In particular, in the extreme cases of one side always coming up or the values being uniformly distributed, it’s possible to generate the result of the roll in O(1) using a naive approach, while my solution will still take logarithmically many steps.</p>
<p>Does anyone have any suggestions for how to solve this problem in a way that is somehow “adaptive” in it’s runtime?</p>
<p><strong>Update:</strong> Based on the answers to this question, I have written up <strong><a href="http://www.keithschwarz.com/darts-dice-coins/" rel="nofollow noreferrer">an article describing many approaches to this problem</a></strong>, along with their analyses. It looks like Vose’s implementation of the alias method gives Θ(<em>n</em>) preprocessing time and O(1) time per die roll, which is truly impressive.  Hopefully this is a useful addition to the information contained in the answers!</p>