<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Miguel Novelo</title>
    <description>The latest articles on DEV Community by Miguel Novelo (@jmnovelovargas).</description>
    <link>https://dev.to/jmnovelovargas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F651298%2Fd0df44df-017b-4595-bc04-6349ef1d9be7.jpg</url>
      <title>DEV Community: Miguel Novelo</title>
      <link>https://dev.to/jmnovelovargas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jmnovelovargas"/>
    <language>en</language>
    <item>
      <title>The Most Interesting Bug I’ve Ever Encountered</title>
      <dc:creator>Miguel Novelo</dc:creator>
      <pubDate>Fri, 16 Jan 2026 03:03:01 +0000</pubDate>
      <link>https://dev.to/jmnovelovargas/the-most-interesting-bug-ive-ever-encountered-51f6</link>
      <guid>https://dev.to/jmnovelovargas/the-most-interesting-bug-ive-ever-encountered-51f6</guid>
      <description>&lt;h2&gt;
  
  
  The Most Interesting Bug I’ve Ever Encountered
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(Or how a library filled up the disk "by magic")&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are annoying bugs, expensive bugs… and then there are those bugs that feel paranormal: you can’t explain what’s happening, the failure mode is not obvious, and the system behaves as if it had a mind of its own.&lt;/p&gt;

&lt;p&gt;This is, without a doubt, the most cryptic—and most interesting—bug I’ve ever debugged.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Symptom: Disk space kept vanishing
&lt;/h2&gt;

&lt;p&gt;It started the way these stories often start:&lt;br&gt;&lt;br&gt;
a “normal” process began to &lt;strong&gt;fill up the disk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No clear memory leak. No obvious exception. No suspicious infinite loop in our code.&lt;br&gt;&lt;br&gt;
Just one painful fact:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The file &lt;code&gt;output.log&lt;/code&gt; kept growing… until the disk ran out of space.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the worst part? &lt;strong&gt;It wasn’t obvious why.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  My approach: not analyzing threads… but figuring out what the process was &lt;em&gt;actually doing&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;The issue was reproducible in a controlled environment, so instead of guessing, I went into debugging mode.&lt;/p&gt;

&lt;p&gt;I started taking &lt;strong&gt;thread dumps&lt;/strong&gt;, not because I suspected concurrency issues, but because I needed to answer a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What on earth is this process doing right now?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thread dumps are often thought of as a tool to inspect thread contention, deadlocks, or runaway parallelism.&lt;br&gt;&lt;br&gt;
But even in a mostly single-threaded process, a thread dump is incredibly useful because it gives you a &lt;strong&gt;snapshot of the call stack&lt;/strong&gt; at that exact moment.&lt;/p&gt;

&lt;p&gt;So I took multiple thread dumps over time and looked for patterns.&lt;/p&gt;

&lt;p&gt;And that’s when I found the clue.&lt;/p&gt;




&lt;h2&gt;
  
  
  The clue: a suspicious loop in the call stack
&lt;/h2&gt;

&lt;p&gt;The call stack kept showing the process doing something like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reading a line from a log file
&lt;/li&gt;
&lt;li&gt;Checking a condition
&lt;/li&gt;
&lt;li&gt;Printing the line using &lt;code&gt;System.out.println(...)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Repeating&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That by itself doesn’t sound terrible… until you realize the log file it was reading was the same file that kept growing.&lt;/p&gt;

&lt;p&gt;At this point I knew I wasn’t dealing with a typical bug inside the business logic.&lt;/p&gt;

&lt;p&gt;I was dealing with something nastier:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A feedback loop.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Root Cause: &lt;code&gt;System.out&lt;/code&gt; had been secretly redirected to a file
&lt;/h2&gt;

&lt;p&gt;Here’s what happened.&lt;/p&gt;

&lt;p&gt;Some library code (not ours!) was doing something like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System.setOut(new PrintStream(new FileOutputStream("output.log")));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In other words, it replaced the global JVM output stream (&lt;code&gt;System.out&lt;/code&gt;) and redirected it to a file.&lt;/p&gt;

&lt;p&gt;Then later, our process would read that same file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a line matched some condition…&lt;/li&gt;
&lt;li&gt;It would “print it to the console” via &lt;code&gt;System.out.println(line)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But &lt;code&gt;System.out&lt;/code&gt; was no longer the console.&lt;/p&gt;

&lt;p&gt;It was the log file itself.&lt;/p&gt;

&lt;p&gt;So the process was effectively doing this:&lt;/p&gt;

&lt;p&gt;1) Read &lt;code&gt;output.log&lt;/code&gt;&lt;br&gt;&lt;br&gt;
2) Find a matching line&lt;br&gt;&lt;br&gt;
3) Append the same line back into &lt;code&gt;output.log&lt;/code&gt;&lt;br&gt;&lt;br&gt;
4) Continue reading&lt;br&gt;&lt;br&gt;
5) Eventually see that line again (or keep tailing the file)&lt;br&gt;&lt;br&gt;
6) Append again&lt;br&gt;&lt;br&gt;
7) Repeat forever  &lt;/p&gt;

&lt;p&gt;A self-feeding loop.&lt;/p&gt;

&lt;p&gt;A log file eating itself alive.&lt;/p&gt;




&lt;h2&gt;
  
  
  The effect: infinite output amplification
&lt;/h2&gt;

&lt;p&gt;This wasn’t your classic infinite loop like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while (true) { ... }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It was worse, because the loop emerged from the interaction between two behaviors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Redirecting a global output sink&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reading and re-printing log content&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It created an “accidental infinite loop” across system boundaries.&lt;/p&gt;

&lt;p&gt;And since disk space is finite, the system didn’t crash—it just kept writing until the disk was completely full.&lt;/p&gt;




&lt;h2&gt;
  
  
  The hardest part: it wasn’t obvious because it wasn’t in our code
&lt;/h2&gt;

&lt;p&gt;This is what made the bug so cryptic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;System.out&lt;/code&gt; is &lt;strong&gt;global state&lt;/strong&gt; for the entire JVM
&lt;/li&gt;
&lt;li&gt;The code that changed it lived inside a library
&lt;/li&gt;
&lt;li&gt;The process behavior looked legitimate in isolation (“read file → print line”)
&lt;/li&gt;
&lt;li&gt;But the hidden coupling created a feedback loop
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once I realized this, the rest was straightforward:&lt;br&gt;&lt;br&gt;
I searched for all occurrences of &lt;code&gt;System.setOut(...)&lt;/code&gt; until I found the offending library call.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix: restoring &lt;code&gt;System.out&lt;/code&gt; as a workaround
&lt;/h2&gt;

&lt;p&gt;Ideally, the library should never have touched &lt;code&gt;System.out&lt;/code&gt; in the first place.&lt;/p&gt;

&lt;p&gt;But I was told escalating and waiting for the library maintainers to fix it would be “a waste of time,” so I implemented a pragmatic workaround:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PrintStream originalOut = System.out;

try {
  libraryCall();
} finally {
  System.setOut(originalOut);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Not pretty, not pure—but it stopped the bleeding.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this bug stands out
&lt;/h2&gt;

&lt;p&gt;This was one of those rare bugs where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the symptoms are severe,
&lt;/li&gt;
&lt;li&gt;the cause is deeply hidden,
&lt;/li&gt;
&lt;li&gt;and the fix is conceptually simple &lt;em&gt;once you see it&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But seeing it required stepping back and asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is this process actually doing?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thread dumps were the key—not for analyzing threads, but as a way to observe execution in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;h4&gt;
  
  
  1) Libraries should never modify global output streams
&lt;/h4&gt;

&lt;p&gt;Messing with &lt;code&gt;System.setOut()&lt;/code&gt; in a shared JVM is playing with fire.&lt;/p&gt;

&lt;h4&gt;
  
  
  2) Feedback loops can appear from “reasonable” code
&lt;/h4&gt;

&lt;p&gt;Each component was individually defensible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“redirect output to a file”&lt;/li&gt;
&lt;li&gt;“read a file and print matching lines”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together? Disaster.&lt;/p&gt;

&lt;h4&gt;
  
  
  3) Thread dumps are not just for concurrency
&lt;/h4&gt;

&lt;p&gt;They’re one of the best tools for answering:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What is my process doing right now?”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Once I understood what was happening, I couldn’t help but admire the bug.&lt;/p&gt;

&lt;p&gt;It was elegant in the worst possible way.&lt;/p&gt;

&lt;p&gt;A perfect example of how global state + I/O can create emergent behavior that looks like black magic.&lt;/p&gt;

&lt;p&gt;And to this day…&lt;/p&gt;

&lt;p&gt;This remains the most interesting bug I’ve ever encountered.&lt;/p&gt;

</description>
      <category>java</category>
      <category>debugging</category>
      <category>softwareengineering</category>
      <category>postmortem</category>
    </item>
    <item>
      <title>Improving Code Clarity with Functional Programming in Java.</title>
      <dc:creator>Miguel Novelo</dc:creator>
      <pubDate>Thu, 28 Sep 2023 01:13:13 +0000</pubDate>
      <link>https://dev.to/jmnovelovargas/my-mistakes-on-java-functional-features-1j6d</link>
      <guid>https://dev.to/jmnovelovargas/my-mistakes-on-java-functional-features-1j6d</guid>
      <description>&lt;p&gt;Today, after a month of working on a new feature, we were ready to have a bug bash, which essentially saved me before ramping this new feature to the public.&lt;/p&gt;

&lt;p&gt;As I began debugging my code, I found myself examining a piece of code that utilizes streams, a crucial tool for functional programming in Java when working with collections.&lt;/p&gt;

&lt;p&gt;I appreciate how elegant, concise, and readable the code becomes when using map to transform items, apply filters, find minimum and maximum values. However, this time, my lack of experience using these features worked against me.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, What happened?
&lt;/h2&gt;

&lt;p&gt;I was working with a piece of code performing some transformations like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entities.stream()
  .map(Entity::getId)
  .map(new EntityCriteria()::setEntity)
  .collect(Collectors.toList())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're more experienced than I was when I wrote this code, you might have already spotted the issue. Allow me to explain:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;entities&lt;/code&gt; is a collection (List) and its elements are type of &lt;code&gt;Entity&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;map(Entity::getId)&lt;/code&gt; will transform the elements into their IDs&lt;/li&gt;
&lt;li&gt;The intention of map(new EntityCriteria()::setEntity) was to transform the entity IDs into EntityCriteria objects with the entityId. However, this happened, but not in the right way.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Understanding the Concepts.
&lt;/h2&gt;

&lt;p&gt;To comprehend what is wrong with number 3, we need to grasp some functional programming concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Entity::getId&lt;/code&gt; from the &lt;code&gt;Entity&lt;/code&gt; class uses the &lt;code&gt;::&lt;/code&gt; operator to retrieve a &lt;code&gt;Function&lt;/code&gt; called &lt;code&gt;getId&lt;/code&gt;. It does NOT retrieve the actual ID.&lt;br&gt;
This &lt;code&gt;Function&lt;/code&gt; will be applied to the &lt;code&gt;Entity&lt;/code&gt; elements to retrieve their IDs because &lt;code&gt;Entity&lt;/code&gt; is a class, and &lt;code&gt;getId&lt;/code&gt; doesn't accept any arguments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When we call &lt;code&gt;map(new EntityCriteria()::setEntity)&lt;/code&gt;, &lt;code&gt;new EntityCriteria()&lt;/code&gt; creates a new object. Then &lt;code&gt;::setEntity&lt;/code&gt; on that object generates a &lt;code&gt;Function&lt;/code&gt; capable of applying &lt;code&gt;setEntity&lt;/code&gt; to the new &lt;code&gt;EntityCriteria&lt;/code&gt; object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Root Cause
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Function&lt;/code&gt; created by &lt;code&gt;new EntityCriteria()::setEntity&lt;/code&gt; is always applied to the same &lt;code&gt;EntityCriteria&lt;/code&gt; object, It doesn't create new objects and then retrieve the function to apply &lt;code&gt;setEntity&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Most Important Question: Why this wasn't caught in Unit Tests ?
&lt;/h2&gt;

&lt;p&gt;The mocked data used in the unit tests, replicated the same buggy logic for transforming the entities, so everything appeared to work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible solutions:
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using Lambdas
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;map(entityId -&amp;gt; new EntityCriteria().setEntity(entityId)) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we use lambdas, we define the function where the &lt;code&gt;entityId&lt;/code&gt; on the left is the input to the function, and the right part is the body of the function (In this case, the transformation logic).&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a new method to be applied in &lt;code&gt;map&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private static EntityCriteria createEntityCriteria(long entityId) {
  return new EntityCriteria().setEntity(entityId);
}

...

entities.stream()
  .map(Entity::getId)
  .map(MyClass::createEntityCriteria)
  .collect(Collectors.toList())

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach creates a &lt;code&gt;Function&lt;/code&gt; that applies &lt;code&gt;createEntityCriteria&lt;/code&gt; and that function generates a new &lt;code&gt;EntityCriteria&lt;/code&gt; object for each element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Everybody makes mistakes, so make sure to thoroughly test your code.&lt;/li&gt;
&lt;li&gt;When writing mock data in unit tests, avoid replicating the logic for building the transformation if that is what you are actually testing.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>java</category>
      <category>lambda</category>
      <category>learning</category>
    </item>
    <item>
      <title>Setting probability to choose something randomly</title>
      <dc:creator>Miguel Novelo</dc:creator>
      <pubDate>Tue, 02 Nov 2021 21:52:22 +0000</pubDate>
      <link>https://dev.to/jmnovelovargas/setting-probability-to-choose-something-randomly-112e</link>
      <guid>https://dev.to/jmnovelovargas/setting-probability-to-choose-something-randomly-112e</guid>
      <description>&lt;p&gt;Playing at Tetris I always wonder how some shapes are most common that they appear than others. Basically, you can expect that you almost never see the line, probably you'll see twice as often the square, then the L shapes and the kind-of zigzag shapes are the most common shapes.&lt;/p&gt;

&lt;p&gt;If you ever think about, how would you implement the shape choosing, just by using the pseudo-random to select the shape, the probability to get any shape will be the same. But we can think some other approaches to change the probability.&lt;/p&gt;

&lt;p&gt;Let's say we have the following shapes with their chances to be picked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Shape:
  def __init__(self, name, chances):
    self.name = name
    self.chances = chances

shapes = [
    Shape("ZigZag", 8),
    Shape("LeftZigZag", 8),
    Shape("L", 4),
    Shape("LeftL", 4),
    Shape("Square", 2),
    Shape("Line", 1),
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are 6 shapes, and the total chances (sum of all chances) are: &lt;code&gt;27&lt;/code&gt;. So the chances of getting a ZigZag will be 8 out of 27, when the chances of getting a line would be 1 out of 27.&lt;/p&gt;

&lt;h1&gt;
  
  
  Approach 1 Creating a list with all the chances
&lt;/h1&gt;

&lt;p&gt;The first approach that came to my mind is creating a list of size 27 and fill it with all the shapes, repeating the shape as many chances it has to appear. This way we have the same chance to pick any of the 27 indexes of the list, but if a shape has 8 slots, this shape will have 8 out of 27 chances to appear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class RandomShapePicker:
  def __init__(self, shapes):
    self.chances = []
    for shape in shapes:
      for _ in range(shape.chances):
        self.chances.append(shape)

  def pick_shape(self):
    return random.choice(self.chances)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Analyzing the performance, to create the &lt;code&gt;RandomShapePicker&lt;/code&gt;, memory will be in function of the total sum of chances (In this case 27) and the time complexity will be in function of the sum of chances as well: &lt;code&gt;O(C), where C is the total sum of chances&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Picking a shape time complexity will be a constant as we get a random index and access directly to that index. We don't need extra space either which is constant as well: &lt;code&gt;O(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This works very well for a small list which can potentially call &lt;code&gt;pick_shape&lt;/code&gt; multiple times as we can expect constant time for these calls.&lt;/p&gt;

&lt;p&gt;The problem with this approach is when the number of choices is large, and we manage large number of &lt;code&gt;chances&lt;/code&gt;. Imagine that the sum of chances is 1000000 which means that our list should have 1M spots. Even if the different choices are low (Let's say 1000).&lt;/p&gt;

&lt;p&gt;For this particular problem would be more efficient not having multiple spots for the same choice. But then, we have to think how we are going to manage that a Line shape has 1/27 chances to appear.&lt;/p&gt;

&lt;h1&gt;
  
  
  Approach 2 Creating a list with the cumulative sum of chances.
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Rethinking our solution:
&lt;/h2&gt;

&lt;p&gt;Picking a number between 0 and 26 (27 chances) the chances of getting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a number between 0 and 7 is 8/27 (ZigZag have 8 out of 27 chances)&lt;/li&gt;
&lt;li&gt;a number between 8 and 15 is 8/27 (LeftZigZag have 8 out of 27 chances)&lt;/li&gt;
&lt;li&gt;a number between 16 and 19 is 4/27 (L have 4 out of 27 chances)&lt;/li&gt;
&lt;li&gt;a number between 20 and 23 is 4/27 (LeftL have 4 out of 27 chances)&lt;/li&gt;
&lt;li&gt;a number between 24 and 25 is 2/27 (Square have 2 out of 27 chances)&lt;/li&gt;
&lt;li&gt;The number 26 is 1/27 (Line have 1 out of 27 chances)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a pattern with the number of chances and the cumulative sum. If we store this cumulative sum in a list, we will have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self.chances = [8, 16, 20, 24, 26, 27]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can use binary search to find the &lt;code&gt;insertion point&lt;/code&gt; for that random number, and then select the shape based on the chances that we have to get that shape:&lt;/p&gt;

&lt;p&gt;For example, if we get number 21, which is in the range of 20 and 23 (4 chances to get a LeftL) The insertion index for that 21 is &lt;br&gt;
3 (The one with the value 24) which is the same index as the LeftL shape.&lt;/p&gt;

&lt;p&gt;The implementation would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class RandomShapePicker:
  def __init__(self, shapes):
    self.shapes = shapes
    self.chances = []
    self.total_chances = 0
    for shape in shapes:
      self.total_chances += shape.chances
      self.chances.append(self.total_chances)

  def pick_shape(self):
    choice = random.random() * self.total_chances
    i = bisect_left(self.chances, choice)
    return self.shapes[i]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implementation will trade off time complexity from pick_shape to improve the time and space complexity for the &lt;code&gt;RandomShapePicker&lt;/code&gt; creation.&lt;/p&gt;

&lt;p&gt;The constructor is now &lt;code&gt;O(N)&lt;/code&gt; time and space complexity (N is the number of choices which is less than number of chances), and pick_shape time complexity is now &lt;code&gt;O(logN)&lt;/code&gt; which is still a decent performance for multiple callings of pick_shape.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We need to think about trade-offs here. Probably is not a bad idea that we are calling a big number of times the pick_shape() or pick_option() and we will only create the object once. Having a constant time to do this can definitely give us the best time performance, but if there is a large number of chances, this can require a large amount of memory. But the second approach can help on that when our number of chances is too high to save some memory and still have a decent time performance.&lt;/p&gt;

</description>
      <category>sampling</category>
      <category>random</category>
      <category>programming</category>
      <category>python</category>
    </item>
  </channel>
</rss>
