<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Competitive programming - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Competitive programming - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 16 Jun 2026 05:48:32 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/competitive-programming/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Binary Exponentiation Algorithm – Explained with Practical Examples ]]>
                </title>
                <description>
                    <![CDATA[ Binary exponentiation, also known as exponentiation by squaring, is a powerful algorithm used to efficiently calculate large powers of numbers. This technique is particularly useful in various fields of computer science, including cryptography, compe... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/binary-exponentiation-algorithm-explained-with-examples/</link>
                <guid isPermaLink="false">670d739fdb0a005601d5afdc</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Competitive programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MathJax ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sahil ]]>
                </dc:creator>
                <pubDate>Mon, 14 Oct 2024 19:40:15 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728672475917/5eeec863-5481-42d8-8b1f-9c92915f570f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Binary exponentiation, also known as exponentiation by squaring, is a powerful algorithm used to efficiently calculate large powers of numbers. This technique is particularly useful in various fields of computer science, including cryptography, competitive programming, and computer graphics.</p>
<p>In this article, we'll explore the concept of binary exponentiation, understand how it works, and implement it in code.</p>
<h2 id="heading-what-is-binary-exponentiation">What is Binary Exponentiation?</h2>
<p>Binary exponentiation is a method to compute \(a^n\) (a raised to the power of n) using only multiplications, instead of the naïve \(O(n)\) multiplications.</p>
<p>This significant improvement in efficiency makes it possible to calculate extremely large powers quickly, even when dealing with modular arithmetic.</p>
<h2 id="heading-how-binary-exponentiation-works">How Binary Exponentiation Works</h2>
<p>The key idea behind binary exponentiation is to break down the exponent into its binary representation and use the properties of exponents to simplify the calculation.</p>
<p>Let's break it down step by step:</p>
<ol>
<li><p>Convert the exponent <code>n</code> to its binary representation.</p>
</li>
<li><p>Initialize the result as 1 and the base as <code>a</code>.</p>
</li>
<li><p>Iterate through each bit of the binary representation of <code>n</code> from right to left: (a). If the current bit is 1, multiply the result by the current base. (b). Square the base (multiply it by itself).</p>
</li>
<li><p>Return the final result.</p>
</li>
</ol>
<p>For example, let's calculate \(3^{13}\):</p>
<ol>
<li><p>Convert 13 to binary: \(13_{10} = 1101_2\)</p>
</li>
<li><p>Initialize result = 1, base = 3</p>
</li>
<li><p>Iterate through the bits:</p>
<ul>
<li><p>Bit 1: result = \(1 *3 = 3\)<em>, base =</em> \(3 *3 = 9\)</p>
</li>
<li><p>Bit 0: result = 3, base = \(9 * 9 = 81\)</p>
</li>
<li><p>Bit 1: result = \(3 *81 = 243\)<em>, base =</em> \(81 *81 = 6561\)</p>
</li>
<li><p>Bit 1: result = \(243 * 6561 = 1,594,323\)</p>
</li>
</ul>
</li>
</ol>
<p>Thus, \(3^{13}=1,594,323.\)</p>
<h2 id="heading-why-binary-exponentiation-is-efficient">Why Binary Exponentiation is Efficient</h2>
<p>The efficiency of binary exponentiation comes from two main factors:</p>
<ol>
<li><p><strong>Reduced number of multiplications</strong>: Instead of performing <code>n-1</code> multiplications as in the naïve approach, we only perform \(O(log n)\) multiplications. This is because we're essentially breaking down the problem into smaller subproblems based on the binary representation of the exponent.</p>
</li>
<li><p><strong>Reuse of previous calculations</strong>: By squaring the base at each step, we're reusing the results of previous calculations, which significantly reduces the overall number of operations needed.</p>
</li>
</ol>
<p>To illustrate this efficiency, consider calculating \(a^{1000000}\). The naïve approach would require 999,999 multiplications, while binary exponentiation would only require about 20 multiplications (as \(\log_2(1000000) \approx 20\)).</p>
<h2 id="heading-algorithm-implementation">Algorithm Implementation</h2>
<p>Let's implement the binary exponentiation algorithm in Python:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_exponentiation</span>(<span class="hljs-params">base, exponent</span>):</span>
    result = <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> exponent &gt; <span class="hljs-number">0</span>:
        <span class="hljs-comment"># If the current bit is 1, multiply the result by the current base</span>
        <span class="hljs-keyword">if</span> exponent &amp; <span class="hljs-number">1</span>:
            result *= base
        <span class="hljs-comment"># Square the base</span>
        base *= base
        <span class="hljs-comment"># Move to the next bit</span>
        exponent &gt;&gt;= <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> result

<span class="hljs-comment"># Example usage</span>
print(binary_exponentiation(<span class="hljs-number">3</span>, <span class="hljs-number">13</span>))  <span class="hljs-comment"># Output: 1594323</span>
</code></pre>
<p>Let's break down the algorithm:</p>
<ol>
<li><p>We initialize <code>result</code> to 1, which is the identity for multiplication.</p>
</li>
<li><p>We use a while loop to iterate until the exponent becomes 0.</p>
</li>
<li><p>We check if the least significant bit of the exponent is 1 using the bitwise AND operator <code>&amp;</code>. If it is, we multiply the result by the current base.</p>
</li>
<li><p>We square the base by multiplying it by itself.</p>
</li>
<li><p>We use the right shift operator <code>&gt;&gt;=</code> to move to the next bit of the exponent.</p>
</li>
<li><p>Finally, we return the result.</p>
</li>
</ol>
<h3 id="heading-time-complexity-analysis">Time Complexity Analysis</h3>
<p>The time complexity of binary exponentiation is \(O(log n)\), where <code>n</code> is the exponent. This is because:</p>
<ol>
<li><p>The number of bits in the binary representation of <code>n</code> is \(\lfloor \log_2 n\rfloor + 1\).</p>
</li>
<li><p>We perform at most two multiplications per bit (one for squaring the base, and potentially one for updating the result).</p>
</li>
</ol>
<p>Therefore, the total number of multiplications is at most \(2(\lfloor \log_2 n \rfloor + 1)\), which simplifies to \(O(\log n)\).</p>
<h2 id="heading-example-problems-and-solutions">Example Problems and Solutions</h2>
<p>Let's look at some algorithmic problems that you can solve efficiently using binary exponentiation, along with detailed explanations of the solutions and how we arrived at using binary exponentiation.</p>
<h3 id="heading-problem-1-modular-exponentiation">Problem 1: Modular Exponentiation</h3>
<p><strong>Problem</strong>: Calculate \(3^{1000000} \bmod 1000000007\).</p>
<p><strong>Approach</strong>:</p>
<ol>
<li><p>We recognize that this problem involves a very large exponent (1000000), which would be impractical to compute using naïve exponentiation.</p>
</li>
<li><p>We also notice that we need to find the result modulo a large prime number (1000000007).</p>
</li>
<li><p>This combination of a large exponent and modular arithmetic is a clear indicator that we should use modular binary exponentiation.</p>
</li>
</ol>
<p><strong>Solution</strong>: We'll modify our binary exponentiation function to include modular arithmetic:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mod_binary_exponentiation</span>(<span class="hljs-params">base, exponent, mod</span>):</span>
    result = <span class="hljs-number">1</span>
    base %= mod
    <span class="hljs-keyword">while</span> exponent &gt; <span class="hljs-number">0</span>:
        <span class="hljs-keyword">if</span> exponent &amp; <span class="hljs-number">1</span>:
            result = (result * base) % mod
        base = (base * base) % mod
        exponent &gt;&gt;= <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> result

print(mod_binary_exponentiation(<span class="hljs-number">3</span>, <span class="hljs-number">1000000</span>, <span class="hljs-number">1000000007</span>))  <span class="hljs-comment"># Output: 624098969</span>
</code></pre>
<p><strong>Explanation</strong>:</p>
<ol>
<li><p>We initialize <code>result</code> to 1 and set <code>base</code> to <code>base % mod</code> to handle cases where the initial base is larger than the modulus.</p>
</li>
<li><p>The main loop works similarly to the original binary exponentiation algorithm, but with two key differences:</p>
<p> a. When updating <code>result</code>, we perform <code>(result * base) % mod</code>. This ensures that <code>result</code> never exceeds <code>mod</code>, preventing integer overflow and maintaining the correct modular result.</p>
<p> b. When squaring <code>base</code>, we perform <code>(base * base) % mod</code> for the same reason.</p>
</li>
<li><p>The bitwise operations (<code>exponent &amp; 1</code> and <code>exponent &gt;&gt;= 1</code>) work exactly as in the original algorithm, allowing us to process the binary representation of the exponent efficiently.</p>
</li>
<li><p>By applying the modulo operation at each step, we ensure that all intermediate results remain within the range [0, mod-1]. This is possible because of the properties of modular arithmetic:</p>
<p> $$(a⋅b)modm=((amodm)⋅(bmodm))modm$$</p>
</li>
</ol>
<p>This problem would be impossible to solve with naïve exponentiation due to the huge result, but modular binary exponentiation makes it tractable by keeping all intermediate results manageable.</p>
<h3 id="heading-problem-2-matrix-exponentiation">Problem 2: Matrix Exponentiation</h3>
<p><strong>Problem</strong>: Given a 2x2 matrix A, calculate An where n = 1000000.</p>
<p><strong>Approach</strong>:</p>
<ol>
<li><p>We observe that we need to raise a matrix to a very large power (1000000).</p>
</li>
<li><p>Matrix multiplication is associative, which allows us to use the same principle as binary exponentiation for numbers.</p>
</li>
<li><p>We recognize that this is a perfect scenario for applying binary exponentiation to matrices.</p>
</li>
</ol>
<p><strong>Solution</strong>: We can use binary exponentiation on matrices. Here's a Python implementation with explanations:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">matrix_multiply</span>(<span class="hljs-params">A, B, mod</span>):</span>
    <span class="hljs-keyword">return</span> np.array([[(A[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>]*B[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>] + A[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>]*B[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>]) % mod, (A[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>]*B[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] + A[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>]*B[<span class="hljs-number">1</span>][<span class="hljs-number">1</span>]) % mod],
                     [(A[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>]*B[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>] + A[<span class="hljs-number">1</span>][<span class="hljs-number">1</span>]*B[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>]) % mod, (A[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>]*B[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] + A[<span class="hljs-number">1</span>][<span class="hljs-number">1</span>]*B[<span class="hljs-number">1</span>][<span class="hljs-number">1</span>]) % mod]])

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">matrix_power</span>(<span class="hljs-params">A, n, mod</span>):</span>
    result = np.eye(<span class="hljs-number">2</span>, dtype=int)
    <span class="hljs-keyword">while</span> n &gt; <span class="hljs-number">0</span>:
        <span class="hljs-keyword">if</span> n &amp; <span class="hljs-number">1</span>:
            result = matrix_multiply(result, A, mod)
        A = matrix_multiply(A, A, mod)
        n &gt;&gt;= <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> result

A = np.array([[<span class="hljs-number">1</span>, <span class="hljs-number">1</span>], [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>]])
n = <span class="hljs-number">1000000</span>
mod = <span class="hljs-number">1000000007</span>

result = matrix_power(A, n, mod)
print(result)  <span class="hljs-comment"># Output: [[690749268 297612485]</span>
                <span class="hljs-comment">#         [297612485 393136783]]</span>
</code></pre>
<p><strong>Explanation</strong>:</p>
<ol>
<li><p><code>matrix_multiply(A, B, mod)</code>:</p>
<ul>
<li><p>This function performs matrix multiplication of two 2x2 matrices, A and B.</p>
</li>
<li><p>Each element of the resulting matrix is computed using the standard matrix multiplication formula, followed by a modulo operation to keep the values manageable.</p>
</li>
</ul>
</li>
<li><p><code>matrix_power(A, n, mod)</code>:</p>
<ul>
<li><p>This function implements binary exponentiation for matrices.</p>
</li>
<li><p>We start with <code>result</code> as the 2x2 identity matrix (created using <code>np.eye(2, dtype=int)</code>).</p>
</li>
<li><p>The main loop follows the same pattern as scalar binary exponentiation: a. If the current bit of n is 1, we multiply <code>result</code> by the current <code>A</code>. b. We square <code>A</code> (by multiplying it with itself). c. We right-shift n to move to the next bit.</p>
</li>
<li><p>All matrix multiplications are done using our <code>matrix_multiply</code> function, which incorporates modular arithmetic.</p>
</li>
</ul>
</li>
</ol>
<p>This matrix exponentiation technique is particularly powerful for solving linear recurrence relations in logarithmic time, as demonstrated here with the Fibonacci sequence.</p>
<h2 id="heading-practice-problems">Practice Problems</h2>
<p>Here are some problems for you to solve using binary exponentiation:</p>
<ol>
<li><p><strong>Modular Exponentiation</strong>: Calculate \(7^{1234567} \bmod 1000000009\). (Hint: Use the <code>mod_binary_exponentiation</code> function from Problem 1 in the examples.)</p>
</li>
<li><p><strong>Last Digit</strong>: Find the last digit of . (Hint: Observe the pattern of last digits of powers of 2 and use binary exponentiation with modulo 10.)</p>
</li>
<li><p><strong>Power Tower</strong>: Calculate the last 3 digits of \(2^{2^{20}}\). (Hint: Use the property of modular arithmetic that \(a^b \bmod m = a^{b \bmod \phi(m)} \bmod m\) where \(\phi\) is Euler's totient function. You'll need to calculate \(2^{20} \bmod \phi(1000)\) first.)</p>
</li>
<li><p><strong>Matrix Chains</strong>: Given a 2x2 matrix A = [[1, 2], [3, 4]], calculate the last two digits of the sum of all elements in \(A^{1000000}\). (Hint: Use matrix exponentiation as in Problem 2 from the examples, but only keep track of the last two digits of each element. You'll need to sum the elements after the final exponentiation.)</p>
</li>
<li><p><strong>Fibonacci Sequence</strong>: Find the 1000000th Fibonacci number modulo 1000000007. (Hint: Use the matrix form of the Fibonacci sequence ([[1, 1], [1, 0]]) and apply matrix exponentiation as shown in Problem 2 of the examples.)</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Binary exponentiation is a powerful technique that can be applied to a wide range of problems involving large exponents. As we've seen in the example and practice problems, it's particularly useful in modular arithmetic, matrix operations, and solving recurrence relations.</p>
<p>By practicing these problems, you'll gain a deeper understanding of how to apply binary exponentiation in various scenarios. Remember, the key is to recognize when a problem involves raising something to a large power, whether it's a number, a matrix, or even a more complex structure.</p>
<p>If you found this explanation of Binary Exponentiation algorithm helpful, you might also enjoy more in-depth programming tutorials and concepts I cover on my <a target="_blank" href="https://blog.theenthusiast.dev">blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Debug Your Code Like a Competitive Programmer – Automate and Save Time ]]>
                </title>
                <description>
                    <![CDATA[ By Alberto Gonzalez Rosales I've been a competitive programmer for many years. And during that time, I have faced the process of debugging on numerous occasions.  In this article, I will try to describe how debugging works in such environments, inste... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/debugging-like-competitive-programmers/</link>
                <guid isPermaLink="false">66d45d5dd7a4e35e3843492e</guid>
                
                    <category>
                        <![CDATA[ Competitive programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ debugging ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 24 Apr 2023 22:03:14 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/nathan-dumlao-Y3AqmbmtLQI-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Alberto Gonzalez Rosales</p>
<p>I've been a competitive programmer for many years. And during that time, I have faced the process of debugging on numerous occasions. </p>
<p>In this article, I will try to describe how debugging works in such environments, instead of depicting it in the regular software development activities we do every day.</p>
<p>But why? You might ask.</p>
<p>The reason is that, because of the short time limit set in these competitions, the participants have to come up with creative ideas to solve all the issues they face. There is no tomorrow for them. It is either "crack or go home". </p>
<p>And sometimes, these ideas can be extrapolated onto the so-called "real world" software development.</p>
<p>Without further ado, let's see what I'm talking about.</p>
<h2 id="heading-some-context"><strong>Some Context</strong></h2>
<p>Competitive Programming contests are a type of competition in which every contestant gets a set of problems. The idea is for them to solve the maximum number of problems they can within the time limit set for the contest, which is usually around two to five hours.</p>
<p>Every problem specifies the format of the input, and it expects some output in response. For example, we could have a problem stating that you need to find the sum of the numbers in a list. In this case, the input would be a list of numbers, and the output would be a single number.</p>
<p>Usually, these competitions take place on automated platforms that can receive solutions for every problem and evaluate those solutions against an entire dataset hidden from the competitors. If a solution returns the expected value for every dataset, it is said to be "Accepted", otherwise it is "Rejected".</p>
<p>As you can imagine, crafting and submitting accurate solutions is an important skill for every participant, but so is being fast. Finding the right balance between correctness and speed is what makes a competitor rise to the top of the standings with more problems solved than their rivals.</p>
<p>Not so far from "real life", isn't it?</p>
<p>It is common to see software companies fighting each other to see which one is the fastest to achieve certain goals or which one gives better results when looking at some particular topic. The balance between doing something right and doing it fast is always critical when working in software development.</p>
<p>And here is where debugging shows up as a key factor, because:</p>
<ul>
<li>It ensures correctness once the "bugs" have been dealt with.</li>
<li>It can affect speed if the process of finding errors takes too long.</li>
</ul>
<p>Let's see what actually happens during competitive programming contests, then!</p>
<h2 id="heading-the-bug-strikes-back"><strong>The "Bug" Strikes Back</strong></h2>
<p>When participating in programming contests, bugs often appear when performance is a defining factor in the solution to a problem. That is, not only is the correct output taken into account, but also how much time your solution takes to return that output for the entire dataset.</p>
<p>The following case is the most common one:</p>
<p>We read a problem, and we know a solution that solves that problem correctly. But unfortunately, it won't be fast enough. No worries, we think about the problem some more and we came up with a solution that is also correct, but this time it will fit in the time limit set for the problem.</p>
<p>We rush into coding our solution, test it a little with some manual test cases, submit it, and... end up receiving a "Rejected" verdict. Which means our solution returned the wrong output for some input.</p>
<p>What do you do in this case?</p>
<p>The approach that most competitors take is to keep testing their solutions against some hand-crafted test cases they come up with. They try to look for edge cases where the solution might return the wrong output, but this is not always easy to do.</p>
<p>The frustration of seeing your program return the correct output for every input you give but knowing there is some hidden test case in which your solution fails can lead you to stop trying a problem that you are almost certain you know the solution to. </p>
<p>This will, of course, impact your performance in the competition because you invested time in a problem you will not end up solving.</p>
<p>So, when the debugging process is taking too long, it is a good alternative to go for the "have the computer find the bugs for you" approach.</p>
<p>Let's see how this works!</p>
<h2 id="heading-debug-smarter-not-more"><strong>Debug Smarter, Not More</strong></h2>
<p>First of all, of course, the computer won't find the bugs for you. The bugs are your own and you will be responsible for finding them. But, what the computer can do is help you generate enough data in a short time to help you find where your solution fails.</p>
<p>Remember that solution we talked about that would give the correct output but wasn't fast enough? Now it's time to make use of it.</p>
<p>Usually, this solution will be easier to code, and less prone to having bugs in it. Let's say we can rely on it because we know we are skilled enough to solve any problem using a <strong>no-brainer</strong> approach.</p>
<p>Do you recall the previous debugging process?</p>
<ol>
<li>Generate hand-crafted input.</li>
<li>Run your solution with that input.</li>
<li>Manually check if the output returned is correct.</li>
<li>If it is not correct, you have a test case to debug thoroughly. Otherwise, repeat step 1.</li>
</ol>
<p>This is highly inefficient for a person to do. Especially steps 1 and 3.</p>
<p>What we can do to speed up this process is to change the checks that we do in step 3 to be automatic instead of manual. And the easiest way to do it is by comparing the outputs returned by both of our solutions (the <strong>no-brainer</strong> and the <strong>buggy</strong>) given the same input.</p>
<p>If we coded our no-brainer solution right (which we are skilled enough to do, of course) then we can ensure that the moment the outputs differ, we have found a test case that is worth having a deeper look into.</p>
<p>Ok. But what about step 1?</p>
<p>The process of generating test cases can be difficult, especially if what we are trying to do is to find one that makes our solution return the wrong output. I mean, if we were able to do that easily then we would have fixed our solution already 😅.</p>
<p>Fortunately, the solution for this issue is to rely on randomness. Yes, you heard me correctly. Randomness provides a spectacular way of generating non-biased input and it works surprisingly well and fast in most cases. </p>
<p>We can replace our hand-crafted process of creating test cases with an automated, easy-to-code, random process that will do the work for us.</p>
<p>Now, the debugging process will be:</p>
<ol>
<li>Generate random input.</li>
<li>Run both solutions with that input.</li>
<li>Check if the outputs differ.</li>
<li>If they do, you have a test case to debug thoroughly. Otherwise, repeat step 1.</li>
</ol>
<p>The difference between both approaches is that the second one can be fully automated, and we will see how to do it next.</p>
<h2 id="heading-automated-debug-mode"><strong>Automated Debug Mode</strong></h2>
<p>Let's automate our debugging process, then!</p>
<p>We will start with this template code in Python, which we will be filling up with the proper code to help us achieve our goals.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">no_brainer</span>():</span>
    <span class="hljs-keyword">pass</span>


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">solution</span>():</span>
    <span class="hljs-keyword">pass</span>


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_input</span>():</span>
    <span class="hljs-keyword">pass</span>


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">debug</span>():</span>
    <span class="hljs-keyword">pass</span>


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    debug()
</code></pre>
<p>The purpose of this implementation is to have the <strong>debug</strong> function generate a new test case by using the <strong>generate_input</strong> function, and supply it to our <strong>solution</strong> and our <strong>no_brainer</strong> solution while the results are the same. The moment the results differ, we can stop generating new test cases and analyze the one that makes our solution fail.</p>
<h3 id="heading-a-real-example">A real example</h3>
<p>Let's make it more interesting by solving a classic algorithmic problem:</p>
<p>"Given a sorted array of integers, and an integer <code>x</code>, find the first index of the array containing the number <code>x</code>, or return <code>-1</code> in case the number doesn't appear in the array".</p>
<p>Now, because we are smart, we know how to solve this problem by using a linear search over the array. The implementation in Python could be something like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">no_brainer</span>(<span class="hljs-params">a, x</span>):</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(a)):
        <span class="hljs-keyword">if</span> a[i] == x:
            <span class="hljs-keyword">return</span> i
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
</code></pre>
<p>This is our <strong>no-brainer</strong> solution. Just a plain for-loop until we find the element we are looking for. The moment we find it, we return the index in which the element can be found. And, in case we don't find it, we return <code>-1</code>, as requested in the problem statement.</p>
<p>Let's assume this solution is not fast enough. Maybe it is because the size of the array is too big and, in the worst case, our solution will end up iterating through all the elements just to find out that the number we were looking for is not present in the array at all.</p>
<p>But, since the array is sorted maybe we can use the Binary Search algorithm, which will indeed speed up the search process. That sounds like a good idea, right? Let's try it!</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">solution</span>(<span class="hljs-params">a, x</span>):</span>
    l = <span class="hljs-number">0</span>
    r = len(a) - <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> l &lt;= r:
        m = (l + r) // <span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> a[m] == x:
            <span class="hljs-keyword">return</span> m
        <span class="hljs-keyword">elif</span> a[m] &lt; x:
            l = m + <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            r = m - <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>
</code></pre>
<p>The code above tries to find the number <code>x</code> in the array, and it also returns <code>-1</code> in case it doesn't find it. Now, it doesn't perform a linear search so we are not expecting it to time out but for some reason, when we submit it for review, we receive a "Rejected" verdict.</p>
<p>As we said before, we will not rush into manual debugging. Instead, let's start by creating a random generator to supply input to both our solutions, hoping we will find the bug soon. Our generating function could be something like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_input</span>():</span>
    n = random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)
    a = [random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>) <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(n)]
    a.sort()
    x = a[random.randint(<span class="hljs-number">0</span>, n - <span class="hljs-number">1</span>)]
    <span class="hljs-keyword">return</span> a, x
</code></pre>
<p>We are generating arrays with sizes at most <code>10</code>, which is a manageable number of elements. We are also making sure the elements are sorted, and we are taking the number <code>x</code> as one of the numbers present in the array.</p>
<p>What we are missing now is just putting all the pieces together, like this:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">debug</span>():</span>
    test_cases = <span class="hljs-number">10000</span>
    <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(test_cases):
        a, x = generate_input()
        no_brainer_output = no_brainer(a, x)
        solution_output = solution(a, x)
        <span class="hljs-keyword">if</span> no_brainer_output != solution_output:
            print(<span class="hljs-string">"Test Case:"</span>)
            print(a, x)
            print(<span class="hljs-string">"Solution Output:"</span>, solution_output)
            print(<span class="hljs-string">"No-Brainer Output:"</span>, no_brainer_output)
            exit()
    print(<span class="hljs-string">"All test cases passed succesfully"</span>)
</code></pre>
<p>By having a glance at the code we can see the benefits of having this as part of our debugging process.</p>
<p>Notice that we have set a limit of <code>10000</code> test cases. That amount is not realistic for a single person to generate, and it sure seems like a sufficiently large number that might ensure we will find a test case where our solutions differ.</p>
<p>On the other hand, once we have fixed our solution, we can run these <code>10000</code> cases again looking for new bugs. The moment all the outputs are the same we would have a stronger belief about the correctness of our algorithm after passing that many tests.</p>
<p>This is the complete version of the implementation, in case you want to see the whole picture:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">no_brainer</span>(<span class="hljs-params">a, x</span>):</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(a)):
        <span class="hljs-keyword">if</span> a[i] == x:
            <span class="hljs-keyword">return</span> i
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">solution</span>(<span class="hljs-params">a, x</span>):</span>
    l = <span class="hljs-number">0</span>
    r = len(a) - <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> l &lt;= r:
        m = (l + r) // <span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> a[m] == x:
            <span class="hljs-keyword">return</span> m
        <span class="hljs-keyword">elif</span> a[m] &lt; x:
            l = m + <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            r = m - <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_input</span>():</span>
    n = random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>)
    a = [random.randint(<span class="hljs-number">1</span>, <span class="hljs-number">10</span>) <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(n)]
    a.sort()
    x = a[random.randint(<span class="hljs-number">0</span>, n - <span class="hljs-number">1</span>)]
    <span class="hljs-keyword">return</span> a, x

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">debug</span>():</span>
    test_cases = <span class="hljs-number">10000</span>
    <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(test_cases):
        a, x = generate_input()
        no_brainer_output = no_brainer(a, x)
        solution_output = solution(a, x)
        <span class="hljs-keyword">if</span> no_brainer_output != solution_output:
            print(<span class="hljs-string">"Test Case:"</span>)
            print(a, x)
            print(<span class="hljs-string">"Solution Output:"</span>, solution_output)
            print(<span class="hljs-string">"No-Brainer Output:"</span>, no_brainer_output)
            exit()
    print(<span class="hljs-string">"All test cases passed succesfully"</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    debug()
</code></pre>
<p>After we run this script, we will get a result like the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676826773373/ac9d1995-dab0-4542-99ee-9bb22773caea.png?auto=compress,format&amp;format=webp" alt="Image" width="196" height="86" loading="lazy"></p>
<p>In this case, the input consists of the array <code>[4, 4, 4, 5, 10]</code> and the number <code>4</code>. This means we need to find the first index where the number <code>4</code> appears in the array.</p>
<p>As you can see, our solution using binary search returns the value <code>2</code>, which is an index where the number <code>4</code> is present, but it is not the first one. On the other hand, our <strong>no-brainer</strong> solution returns the value <code>0</code>, which is the first index whose value is equal to <code>4</code>.</p>
<p>And, just like that, in a matter of seconds, we have generated a test case that shows that our solution fails. Now we can proceed to analyze it thoroughly and fix our code.</p>
<p><strong>Note</strong>: As an exercise for you, I will skip the part where I explain what is wrong with the implementation above. If you realize what the issue is, let me know so we can start a discussion and keep learning as a community.</p>
<p>A possible fix to our implementation is the following:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">solution</span>(<span class="hljs-params">a, x</span>):</span>
    l = <span class="hljs-number">0</span>
    r = len(a) - <span class="hljs-number">1</span>
    pos = <span class="hljs-number">-1</span>
    <span class="hljs-keyword">while</span> l &lt;= r:
        m = (l + r) // <span class="hljs-number">2</span>
        <span class="hljs-keyword">if</span> a[m] &gt;= x:
            pos = m
            r = m - <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            l = m + <span class="hljs-number">1</span>

    <span class="hljs-keyword">return</span> pos
</code></pre>
<p>Let's see that when we run the script, now that we have modified our solution, we get the gratifying result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1676828190631/bb3344dc-6313-4076-b921-529a6868b2a0.png?auto=compress,format&amp;format=webp" alt="Image" width="309" height="22" loading="lazy"></p>
<p>Which will give us the courage to submit our implementation again.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, we have seen an effective approach for generating test cases to stress-test our solutions. We have automated the process of crafting each case and checking for correctness, making it less time-consuming to find bugs in the code.</p>
<p>The approach seen here is one of the most effective ones used in Competitive Programming, but it sure can be extrapolated to use cases in "real world" software development. </p>
<p>It also shows how you can take advantage of the computing power present in the devices we use every day to speed up the debugging process and deliver features that have been tested thoroughly while still being able to beat your deadlines.</p>
<p>During my Competitive Programming journey through college, I implemented this type of debugging not only in individual competitions but in team contests as well. As a result of that, my teammates and I gained speed when competing and were able to achieve amazing results.</p>
<p>We all agree that this method of debugging played an important role in our achievements as competitive programmers. We went all the way from programming enthusiasts to ICPC World Finalists by making sure that we were the most productive we could be during the limited time we had in every contest. And I assure you: <strong>there is no contest without debugging</strong>.</p>
<p>I recommend you give it a try. Let me know your results!</p>
<p>👋 Hello, I'm Alberto, <strong>Software Developer at</strong> <a target="_blank" href="https://dowhile.se/"><strong>doWhile</strong></a>, Competitive Programmer, Teacher, and Fitness Enthusiast.</p>
<p>🧡 If you liked this article, consider sharing it.</p>
<p>🔗 <a target="_blank" href="https://bio.link/albexl"><strong>All links</strong></a> | <a target="_blank" href="https://twitter.com/albe_xl"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/albexl/"><strong>LinkedIn</strong></a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Mythbusting Competitive Programming – You Don't Need to Learn It ]]>
                </title>
                <description>
                    <![CDATA[ By Mehul Mohan Now that I have your attention with the post title, let me go in-depth on my views of competitive programming. What is competitive programming? Competitive programming is a sport. You have to solve a problem with code that is fast, con... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/mythbusting-competitive-programming/</link>
                <guid isPermaLink="false">66d4606c55db48792eed3f8f</guid>
                
                    <category>
                        <![CDATA[ Competitive programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sat, 27 Jun 2020 20:30:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/06/cp.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mehul Mohan</p>
<p>Now that I have your attention with the post title, let me go in-depth on my views of competitive programming.</p>
<h2 id="heading-what-is-competitive-programming">What is competitive programming?</h2>
<p>Competitive programming is a sport. You have to solve a problem with code that is fast, consumes the minimum amount of memory, and is often <em>practically unreadable.</em> </p>
<p>It is super popular among university students and those trying to get into big companies, primarily because it helps them get placed in those companies. Unfortunately, millions of people are hired because of some knowledge they would never use in their jobs.</p>
<h2 id="heading-the-system-is-broken">The system is broken</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-27-at-6.46.26-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here's another example from <a target="_blank" href="https://twitter.com/Nienhuys/status/1276044242855624704">Hen-Wen</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/06/Screenshot-2020-06-27-at-6.52.17-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>There are tons of examples out there I can think of. </p>
<p>The creator of homebrew – a package manager used by almost everyone running macOS? Rejected. The creator of WhatsApp? Rejected by Facebook and Twitter. </p>
<p>So what is happening here? Are these people not qualified enough to work in these MNCs?</p>
<p>No, the answer is that these guys can develop useful tools and write great software with top-notch code quality, but they probably fail to (re)invent an algorithm to invert a binary tree in a 30-minute time limit. </p>
<p>Some of the best code written ever was not written in 30 minutes. Some of the best algorithms written in Linux kernel used even today were not written in 30 minutes by Linus. Some of the best UIs like Stripe was not designed in 30 minutes. </p>
<p>So how can some random HR person in some random company decide your worth in 30 minutes?</p>
<p>This is how companies judge your "feasibility" – by seeing if you can solve a toy problem completely unrelated to any work you might have done in the past, or you might do in the future.</p>
<h3 id="heading-can-this-be-fixed">Can this be fixed?</h3>
<p>I don't know. I can complain and yell all I want, but I honestly don't know how companies can evaluate a person applying for a job quickly and correctly. </p>
<p>If you want quick, you'll lose a lot of good candidates like the ones mentioned above. If you want to lose no good candidates, the interview might last for way too long – much longer than the company can afford.</p>
<h2 id="heading-competitive-programming-real-world-programming">Competitive Programming !== Real World Programming</h2>
<p>Interviews for companies are more of an exam where you have to memorize and learn about things you won't use after getting the job. </p>
<p>You think you might need to learn Dijkstra's algorithm to work on Google Maps, but seriously, do you think Google is going to hand over one of their core products to someone new to the company? Do you think you'll get no help whatsoever from your peers?</p>
<p>You will probably be working on the interface for the product, or distributed systems rather than working on one of Google's cor algorithms. This means all of your "competitive programming" knowledge is of no use.</p>
<p>You'll find almost no use for competitive programming in the real world. No algorithm running on production Microsoft servers is written in unreadable code, with short and meaningless variable names, undocumented and optimized only for speed and not readability or maintenance.</p>
<p>Minifying and performance improvement comes later on, with automated tools a lot of the time. Chances are, if you are a competitive coder, you developed the bad habit of writing ugly code. </p>
<p>Anyone can write code for machines. The question is, can you write code for humans?</p>
<h2 id="heading-but-theres-hope">But there's hope</h2>
<p>Sitting for interviews like this and hoping you can solve a toy question you prepared for 3-5 months learning just DSA and competitive programming is one way. </p>
<p>There's another way – it'll work with fewer companies and people, but you'll enjoy it, and learn a lot of real-world things along the way. You'll also be more useful than those people who only learn "competitive coding" for the sake of it.</p>
<p>Build something. Anything. And then build more on top of that. Have a strong portfolio. Have a complete skillset which is useful for companies. Have mastery with a tech stack – own it. Have projects, blogs, experience to show that you are what is in your resume. Build connections, network with people, ask for their recommendations. </p>
<p>In a lot of places, competitive coding is not the only way to clear an interview – there are all kinds of people running all kinds of companies. A person who agrees with my PoV, and is running a company would not be hiring people on their "competitive" knowledge alone.</p>
<p>Your work can take you places you couldn't imagine. The easiest way is to always follow the crowd. But nothing good comes easy, at least if you're ambitious enough. Mixing just the right amount of ambition and courage can do wonders. </p>
<p>The world needs great programmers to progress, to move humanity forward, not people who can get hired.</p>
<h2 id="heading-dont-confuse-dsa-with-competitive-programming">Don't confuse DSA with Competitive Programming</h2>
<p>I did not want to write this section initially, but I knew too many people will confuse this. DSA - Data Structures and Algorithms is something different. Heap, Maps, Arrays, Vectors, Linked Lists, .etc, all these are super helpful in real-world programming too.</p>
<p>The fun part is you can develop that understanding with experience, too. I never explicitly learned about "heap" using some big 50-hour DSA course. And if you are learning to program, you don't need a very very deep understanding of that too. </p>
<p>DSA in depth is required when you want to learn computer science, not programming. Understand the difference, computer science is the theory – programming is practical.</p>
<p>Be <strong>aware</strong> of things that exist, algorithms that exist, and data structures that exist. You don't need to learn or memorize them all. It sounds insanely stupid to me to memorize or learn something which is rarely used when I can get it with a bit of help from colleagues and the internet.</p>
<h2 id="heading-my-story">My story</h2>
<p>I'm <strong>not</strong> a competitive coder, probably the only CS undergrad in my university who never touched competitive coding in <strong>college</strong>. </p>
<p>Why? Because I tried it 4-5 years ago and hated it. Why? Because I could see myself spending 3-5 hours of my day, every day, solving problems that got me nothing. I knew a thing or two more about approaching the next question, but was that enough to make an impact? Was that enough to stand out from the crowd?</p>
<p>What good was I doing? It felt like I was wasting time on questions that were already solved. It might be different for everyone, but I am happy when I see other people using the things I programmed (I started as a web developer by then). </p>
<p>I just couldn't stand wasting my time learning something I would never use in the real world. I used to participate in Google's Code Jam and Facebook's Hacker Cup back in the day. But soon I got bored and frustrated, for the lack of a better word, and never really got back to it. Getting a job or internship didn't concern me, it never did.</p>
<p>I sat for Google interviews once on campus. They had a resume shortlisting round as the first round, unlike all the other companies where the first round was, wait for it, <strong>competitive coding round.</strong> Well there went the 7 years of web development and systems experience down the drain. </p>
<p>Anyway, for Google, I was the only person to be shortlisted with a GPA of 7.5 (the highest GPA is 10 in India). The rest of the 10-15 people were above 8.5 or 9. </p>
<p>I didn't get past the competitive round again, but that taught me that it was possible to break into the first round of a company like Google with just your resume. Therefore, it's important to work on that.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>TL;DR – You don't need to learn competitive coding to succeed in life. You need to learn something you like so much that you master it, and you're unbeatable in your field. That's all. </p>
<p>Have views and opinions? Connect with me on <a target="_blank" href="https://twitter.com/mehulmpt">Twitter</a> and <a target="_blank" href="https://instagram.com/mehulmpt">Instagram</a> and let's talk!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Change the signs: how to use dynamic programming to solve a competitive programming question ]]>
                </title>
                <description>
                    <![CDATA[ By Sachin Malhotra If you’re a competitive programmer like I am, one of the best feelings in the world is seeing your program getting accepted on first try on one of the most famous programming platforms, CodeChef. I was an avid competitive programme... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/just-change-the-signs-how-to-solve-a-competitive-programming-question-f9730e8f04a9/</link>
                <guid isPermaLink="false">66c3595df83dfae169b2c001</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Competitive programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Dynamic Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Problem Solving ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 01 Jun 2018 22:00:05 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*kdC2W2WKEjPIG1pRCk0qmg.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Sachin Malhotra</p>
<p>If you’re a competitive programmer like I am, one of the best feelings in the world is seeing your program getting accepted on first try on one of the most famous programming platforms, <a target="_blank" href="https://www.codechef.com/">CodeChef</a>.</p>
<p>I was an avid competitive programmer during undergrad, and then lost touch with it when working as a developer @Hike. However, I recently started out into this adventurous world of programming again, all thanks to my friend <a target="_blank" href="https://www.freecodecamp.org/news/just-change-the-signs-how-to-solve-a-competitive-programming-question-f9730e8f04a9/undefined">Divya Godayal</a>.</p>
<p>The <a target="_blank" href="https://www.codechef.com/MAY18">CodeChef May 2018 Long Challenge</a> ended about an hour ago, and I decided to write this article as a post describing one of the questions in the competition.</p>
<p>Without wasting any more time, let’s get to it.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Y6UspCo7zHVxvZE-xRG3pERSJQy4CfD6EGU3" alt="Image" width="800" height="1091" loading="lazy"></p>
<h3 id="heading-unravelling-the-problem-statement">Unravelling the Problem Statement</h3>
<p>Let’s look at some examples to better understand what the problem statement is asking for.</p>
<p>Consider the following number sequence.</p>
<pre><code><span class="hljs-number">4</span> <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span>
</code></pre><p>Now the question asks us to perform a certain operation (possibly 0 times, leaving the sequence unchanged). We can negate a certain subsequence of numbers and get a new sequence.</p>
<pre><code><span class="hljs-number">-4</span> <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">24</span> <span class="hljs-number">-3</span> <span class="hljs-number">1</span> <span class="hljs-number">-24</span> <span class="hljs-number">3</span> <span class="hljs-number">-1</span> <span class="hljs-number">24</span> <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">-2</span><span class="hljs-number">-4</span> <span class="hljs-number">-3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> etc.
</code></pre><p>The question says that the resulting sequence should satisfy the following constraint:</p>
<p><strong>The sum of elements of any substring with length greater than 1 is strictly positive.</strong></p>
<p>Clearly, the following sequences are not valid:</p>
<pre><code><span class="hljs-number">-4</span> <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">24</span> <span class="hljs-number">-3</span> <span class="hljs-number">1</span> <span class="hljs-number">-2</span> <span class="hljs-number">4</span> <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">-2</span> <span class="hljs-number">-4</span> <span class="hljs-number">-3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">-4</span> <span class="hljs-number">-3</span> <span class="hljs-number">-1</span> <span class="hljs-number">-24</span> <span class="hljs-number">3</span> <span class="hljs-number">-1</span> <span class="hljs-number">-2</span>
</code></pre><p>We only have 2 valid subsequences that can be obtained by performing the operation mentioned above. <strong>Note:</strong> we haven’t written down all the possible subsequences. That would be 2^n, that is 16 in this case, because for every number we have two options. Either to negate it, or not.</p>
<p>So the two valid sequences are:</p>
<pre><code><span class="hljs-number">4</span> <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span>
</code></pre><p>and</p>
<pre><code><span class="hljs-number">4</span> <span class="hljs-number">3</span> <span class="hljs-number">-1</span> <span class="hljs-number">2</span>
</code></pre><p>The original sequence would always be one of the valid sequences as all the numbers in it are positive.</p>
<p>Now the question asks us to find the sequence with the minimum sum. So for the example we have considered, the sequence required would be <code>4 3 -1 2</code> .</p>
<h3 id="heading-would-greedy-work">Would Greedy Work?</h3>
<p>A greedy approach in this question would be that if it is possible to negate a number while satisfying the given constraints, then we should negate that number. This approach however, would not always give the right results. Consider the following example.</p>
<pre><code><span class="hljs-number">4</span> <span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">2</span>
</code></pre><p>Here, it is possible to have these three valid sets of numbers:</p>
<pre><code><span class="hljs-number">4</span> <span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">2</span>           <span class="hljs-number">4</span> <span class="hljs-number">-1</span> <span class="hljs-number">3</span> <span class="hljs-number">2</span>           <span class="hljs-number">4</span> <span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">-2</span>
</code></pre><p>Clearly, both the numbers 2 and 1 can be negated. But not both of them at the same time. If we negate a number greedily — that is, if a number can be negated, then we negate it — then it is possible that we might end up negating the number 1. Then you won’t be able to negate the number 2. This would give us a suboptimal solution.</p>
<p>So this Greedy approach would not work here. We have to <strong>“try out a specific choice of whether to negate or not for a number and see what choice gives us the optimal solution”<em>.</em></strong></p>
<p>This smells like Dynamic Programming.</p>
<h3 id="heading-good-ol-dynamic-programming">Good ol’ Dynamic Programming</h3>
<p>One of the most interesting algorithmic techniques out there, and possibly one of the most dreaded, is dynamic programming. This is the technique we are going to use to solve this particular problem.</p>
<p>Two of the most important steps in any dynamic programming problem are:</p>
<ol>
<li>Identifying the recurrent relation.</li>
<li>Figuring out what to <a target="_blank" href="https://www.interviewcake.com/concept/java/memoization"><strong>memoize</strong></a><strong>. (not memoRize :P)</strong></li>
</ol>
<p>The DP-based approach here is divided into two basic parts.</p>
<ul>
<li>One is the main recursion that we use to find out the <strong>minimum sum of the final set</strong>. Note, the dynamic programming is not directly used to obtain the final set, just the sum of the final set of numbers. So our dynamic programming approach would correctly find out the sum for the example given above as 8. <code>4 + 3 + (-1) + 2 = 8</code> .</li>
<li>What we actually need is the final modified set of numbers where some (possibly none) of the numbers are negated. We use the concept of a <strong>parent pointer</strong> and <strong>backtracking</strong> to find out the actual set of numbers.</li>
</ul>
<p>Let’s move onto our recursion relation for our dynamic programming approach.</p>
<p>Before describing the recursive relation an important observation to make here is that if a number has been negated, <strong>then any adjacent number to it can not be negative</strong>. That is, two adjacent numbers cannot be negative as that would give a substring of length 2 whose sum is negative, and that is not allowed according to the question.</p>
<p>For the recurrence relation, we need two variables. One is the index number of where we are in the array, and one is a boolean value that tells us if the previous number (one left to the previous number) is negated or not. So if the current index is <code>i</code>, then the boolean value would tell us if the number at <code>i — 2</code> was negated or not. You will know the importance of this boolean variable in the next paragraph.</p>
<p>We need to know in <code>O(1)</code> if a number <strong>can</strong> be negated or not. Since we are following a recursion with memoization-based solution, whenever we are at an index <code>i</code> in the recursion, we are sure that the numbers to the right (<code>i+ 1</code> onwards) have not been processed up to this point. This means that all of them are still positive.</p>
<p>The choice of whether the number at index <code>i</code> can be negated is dependent upon the right hand side (if there is one) and the left hand side (if there is one). The right hand side is easy. All we need to check is if</p>
<pre><code>number[i] &lt; number[i + <span class="hljs-number">1</span>]
</code></pre><p>because if this is not true, then adding these two would give a negative value for the substring <code>[i, i + 1]</code> thus making it an invalid operation.</p>
<p>Now comes the tricky part. We need to see if negating the number at <code>i</code> will cause a substring of negative sum to the left or not. When we reach the index <code>i</code> in our recursion, we have already processed the numbers before it, and some might have been negated as well.</p>
<p>So say we have this set of numbers <code>4 1 2 1</code> and we had negated the first <code>1</code> and we are now processing the last number ( <code>1</code> ).</p>
<pre><code><span class="hljs-number">4</span> <span class="hljs-number">-1</span> <span class="hljs-number">2</span> [<span class="hljs-number">1</span>]
</code></pre><p>The last number in square brackets is the one we are processing right now. As far as the right hand side is concerned, since there is none, we can negate it. We need to check if negating this 1 at index 3 (0 based indexing) would cause any substring to the left of ≤ 0 sum. As you can see, it will produce such a substring.</p>
<pre><code><span class="hljs-number">-1</span> <span class="hljs-number">2</span> <span class="hljs-number">-1</span>
</code></pre><p>This substring would have a 0 sum, and that is invalid according to the question. After negating a subsequence of numbers, the substrings in the final set should have a sum which is strictly positive. All the substrings of length &gt; 1.</p>
<p>We cannot apply the following approach here directly:</p>
<pre><code><span class="hljs-keyword">if</span> number[i] &lt; number[i - <span class="hljs-number">1</span>], then it is good to go on negation.
</code></pre><p>because, although <code>1 &lt;</code>; 2 , if we negate that last 1 as well we will have an invalid set of numbers as seen above. So this simple approach or check won’t work here.</p>
<p>Here comes the boolean variable which tells us if, given an index <code>i</code>, the number at <code>i — 2</code> was negated or not. Consider the two scenarios.</p>
<ul>
<li>Yes, the number at index <code>i — 2</code> was negated like in the example just showcased. In that case, negation of the number at <code>i — 2</code> would have a capacity reduction for number at <code>i — 1</code>. In the example <code>4 1 2 1</code> , negating the 1 at index 1(0 based indexing) would reduce the capacity of the number 2 (at index 2) by 1. We refer to remaining values of numbers as capacities here. We need to consider this reduced capacity when performing the check to see if a number can be negated or not.</li>
</ul>
<pre><code>number[i] &lt; reducedCapacityOfNumberAt(i - <span class="hljs-number">1</span>)
</code></pre><ul>
<li>In case the number at index <code>i — 2</code> wasn’t negated, the number at <code>i — 1</code> is at it’s full capacity. The simple check</li>
</ul>
<pre><code>number[i] &lt; number[i - <span class="hljs-number">1</span>]
</code></pre><p>would be enough to see if we can negate the number at index <code>i</code> .</p>
<p>Let’s look at the code for the recursion containing all the ideas discussed above.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/a4tshHUm1WyoHHO0hK-050EfDySLR3KHVwzY" alt="Image" width="800" height="648" loading="lazy"></p>
<p>That’s all nice and dandy. But, this is just recursion, and the heading says dynamic programming. That means there would be overlapping subproblems. Let us look at the recursion tree to see if there are any.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-6EItwtVtgzqUHrsbEJODoMoxV2woN6iN7Nv" alt="Image" width="800" height="687" loading="lazy"></p>
<p>As you can see, there are overlapping subproblems in the recursion tree. That is why we can use memoization.</p>
<p>The memoization is as simple as:</p>
<pre><code><span class="hljs-string">""</span><span class="hljs-string">" This comes at the top. We check if the state represented by the tuple of the index and the boolean variable is already cached "</span><span class="hljs-string">""</span>
</code></pre><pre><code><span class="hljs-keyword">if</span>(memo[i][is_prev_negated] != INF) {    <span class="hljs-keyword">return</span> memo[i][is_prev_negated];}
</code></pre><pre><code>...... CODE
</code></pre><pre><code># Cache the minimum sum <span class="hljs-keyword">from</span> <span class="hljs-built_in">this</span> index onwards.memo[i][is_prev_negated] = min(pos, neg);
</code></pre><pre><code># The parent pointer is used <span class="hljs-keyword">for</span> finding out the final set <span class="hljs-keyword">of</span> #sparent[i][is_prev_negated] = min(pos, neg) == pos ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>;
</code></pre><p>As pointed out earlier, this recursive approach would return the minimum sum of the set of numbers possible after making the valid set of modifications to them.</p>
<p>The question, however, asks us to actually print the final set of numbers that gives the minimum sum after making such modifications. For that, we need to use a parent pointer that would tell us at every index and boolean variable <code>is_prev_negated</code> ’s value as to what optimal action was taken.</p>
<pre><code>parent[i][is_prev_negated] = min(pos, neg) == pos ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>;
</code></pre><p>So we simply store 1 or -1 depending upon if negating the number at index i (if possible!) gave us the minimum sum or if choosing to ignore it gave the minimum sum.</p>
<h3 id="heading-backtracking">Backtracking</h3>
<p>Now comes the part where we backtrack to find the solution to our original problem. Note that the decision for the very first number is what propagates the recursion further. If the first number was negated, the second number would be positive and the third number’s decision can be found using <code>parent[2][true]</code>. Similarly, if the first number wasn’t negated, then we move onto the second number and it’s decision can be found using <code>parent[1][false]</code> and so on. Let’s look at the code.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-rimpa-Iqfb1y22u7qbQZgjxkU-A2ziBQZrW" alt="Image" width="800" height="591" loading="lazy"></p>
<h3 id="heading-a-better-approach">A Better Approach</h3>
<p>If you take a look at the space complexity of the solution suggested, you will see that it’s a 2 dimensional dynamic programming solution because the state of the recursion is represented by two variables i.e. the index <code>i</code> representing what number of the array we are considering and then the boolean variable <code>is_prev_negated</code> . So the space complexity and the time complexity would be O(n*2) which is essentially O(n).</p>
<p>However, there is a slightly better approach as well to solving this problem as suggested by <a target="_blank" href="https://www.freecodecamp.org/news/just-change-the-signs-how-to-solve-a-competitive-programming-question-f9730e8f04a9/undefined">Divya Godayal</a>. This problem can even be solved by 1 dimensional dynamic programming based solution.</p>
<p>Essentially, the boolean variable <code>is_prev_negated</code> is helping us to decide if we can negate a given number at index <code>i</code> or not as far as the left hand side of the array is concerned i.e. <code>all the numbers from 0 .. i-1</code> because the right hand side is anyways safe as all the numbers on that side are positive (as the recursion hasn’t reached them yet). So for the right hand side we simply checked the number at <code>i+1</code> but for the left hand side of index <code>i</code> we had to make use of the boolean variable <code>is_prev_negated</code> .</p>
<p>It turns out, that we can simply skip this boolean variable altogether and simply look ahead to decide if a number can be negated or not. Which simply means if you are at an index <code>i</code>, you check if that element along with the element at <code>i+2</code> have the capacity to swallow the element at <code>i+1</code> i.e.</p>
<pre><code>numbers[i] + numbers[i+<span class="hljs-number">2</span>] &gt;= numbers[i+<span class="hljs-number">1</span>  (SWALLOW)
</code></pre><p>If there is a such a possibility, then we directly jump to <code>i+3</code>if we negate element at <code>i</code> because element at <code>i+1</code> and <code>i+2</code> both can’t be negative in such a scenario.</p>
<p>In case the swallow condition is not satisfied and we end up negating the number at index <code>i</code> , then we would jump to index <code>i+2</code> because in any case, two consecutive numbers cannot be negated. So if the number at <code>i</code> was negated, then the number at <code>i+1</code> has to be positive. The swallow check is to see if the number at <code>i+2</code> would definitely have to be positive or if we can exercise the choice of whether to negate or not there.</p>
<p>Have a look at the code for a better understanding.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xfOALns0BeiZRPCX-3eL6gpcwxRQu4DCn0W7" alt="Image" width="800" height="587" loading="lazy"></p>
<p>Hence, just a single variable i.e. the index is used to define the state of the recursion. So the time and space complexity, both got reduced to half of what they were in the previous solution.</p>
<p>I hope you were able to grasp the working of the algorithm described above and how the dynamic programming technique fits into this problem. I think it’s an interesting problem, because you not only have to use dynamic programming but also the concept of parent pointer to retrace the steps through the optimal solution and get the answer required in the question.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
