<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-06-25T00:09:59+00:00</updated><id>/feed.xml</id><title type="html">Seroze’s blog</title><subtitle>Personal blog of seroze.</subtitle><entry><title type="html">Philosophy, Part 1: Think in Failure Patterns</title><link href="/philosophy-part-1/" rel="alternate" type="text/html" title="Philosophy, Part 1: Think in Failure Patterns" /><published>2026-06-23T18:30:00+00:00</published><updated>2026-06-23T18:30:00+00:00</updated><id>/philosophy-part-1</id><content type="html" xml:base="/philosophy-part-1/"><![CDATA[<p>This is the first in a series where I jot down ideas that quietly change how I
make decisions. Starting with one borrowed from the world of investing.</p>

<h2 id="invert-study-failure-then-avoid-it">Invert: study failure, then avoid it</h2>

<p>One of the philosophies I keep coming back to — preached relentlessly by Charlie
Munger (Warren Buffett’s longtime partner at Berkshire Hathaway, who shares the
same defensive instinct) — is deceptively simple:</p>

<blockquote>
  <p>Don’t ask “how do I succeed?” Ask “how do I fail?” — then don’t do that.</p>
</blockquote>

<p>Instead of chasing the elusive recipe for success, you catalogue the <strong>failure
patterns</strong>: the recurring ways things blow up. Then you build your life, your
code, your decisions to steer clear of them. Munger calls this <em>inversion</em> —
“all I want to know is where I’m going to die, so I’ll never go there.”</p>

<p>Munger borrowed the phrase “invert, always invert” from the 19th-century
mathematician Carl Jacobi. It sounds like a cute reframing, but it’s a genuinely
different way to think.</p>

<h2 id="why-inversion-works">Why inversion works</h2>

<ul>
  <li><strong>Failures are fewer and more legible than successes.</strong> There are a thousand
ways to build a great company and only a handful of ways to reliably kill one
(run out of cash, lose trust, over-leverage). The failure set is smaller and
easier to memorize.</li>
  <li><strong>Avoiding stupidity beats seeking brilliance.</strong> Buffett’s edge isn’t a string
of genius bets — it’s decades of <em>not</em> doing the dumb thing when everyone else
did. You don’t have to be clever if you’re consistently not foolish.</li>
  <li><strong>It’s defensive, and defense compounds.</strong> Survive long enough and avoid the
catastrophic mistakes, and time does the rest of the work for you.</li>
</ul>

<h2 id="how-i-apply-it">How I apply it</h2>

<p>Whenever I’m about to make a decision, I run the inversion:</p>

<ol>
  <li><strong>List the failure modes.</strong> “What are all the ways this could go badly?”</li>
  <li><strong>Rank them by damage.</strong> Some failures are recoverable; some are terminal.
Pay attention to the terminal ones first.</li>
  <li><strong>Engineer them out.</strong> Design the decision so the catastrophic paths are
simply unavailable, not just unlikely.</li>
</ol>

<p>In engineering this is second nature — it’s literally what a <em>pre-mortem</em> or a
failure-mode analysis is. You imagine the system has already crashed and work
backwards to the cause. The Buffett insight is that the same move works for
careers, relationships, and money, not just distributed systems.</p>

<h2 id="the-one-line-takeaway">The one-line takeaway</h2>

<p>You don’t need a map of every road to success. You need a map of the cliffs —
and the discipline to not drive off them.</p>

<p><em>Next in the series: more borrowed wisdom, one mental model at a time.</em></p>]]></content><author><name>Seroze</name></author><category term="philosophy" /><category term="philosophy" /><category term="mental-models" /><category term="decision-making" /><summary type="html"><![CDATA[This is the first in a series where I jot down ideas that quietly change how I make decisions. Starting with one borrowed from the world of investing.]]></summary></entry><entry><title type="html">A Primer on JavaScript</title><link href="/primer-on-javascript/" rel="alternate" type="text/html" title="A Primer on JavaScript" /><published>2026-06-21T18:30:00+00:00</published><updated>2026-06-21T18:30:00+00:00</updated><id>/primer-on-javascript</id><content type="html" xml:base="/primer-on-javascript/"><![CDATA[<p>If you already know Python and Java, JavaScript is easy to pick up. It sits
somewhere between the two:</p>

<ul>
  <li><strong>Like Python</strong>, it is <em>dynamically typed</em> — you don’t declare types, and a
variable can hold a string now and a number later.</li>
  <li><strong>Like Java</strong>, the <em>syntax</em> is C-style — curly braces for blocks, semicolons
at the end of statements, <code class="language-plaintext highlighter-rouge">for</code> loops with the classic three-part header.</li>
</ul>

<p>This post collects the handful of things worth knowing up front.</p>

<h2 id="primitive-types">Primitive types</h2>

<p>Unlike some languages, JavaScript doesn’t split numbers into <code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">float</code>,
<code class="language-plaintext highlighter-rouge">double</code>, etc. — there is just one <code class="language-plaintext highlighter-rouge">number</code> type that covers integers and
floating-point alike. In total JavaScript has <strong>7 primitive types</strong>:</p>

<table>
  <thead>
    <tr>
      <th>Type</th>
      <th>Example</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">number</code></td>
      <td><code class="language-plaintext highlighter-rouge">42</code>, <code class="language-plaintext highlighter-rouge">3.14</code>, <code class="language-plaintext highlighter-rouge">NaN</code>, <code class="language-plaintext highlighter-rouge">Infinity</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">string</code></td>
      <td><code class="language-plaintext highlighter-rouge">"hello"</code>, <code class="language-plaintext highlighter-rouge">'world'</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">boolean</code></td>
      <td><code class="language-plaintext highlighter-rouge">true</code>, <code class="language-plaintext highlighter-rouge">false</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">undefined</code></td>
      <td><code class="language-plaintext highlighter-rouge">let x;</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">null</code></td>
      <td><code class="language-plaintext highlighter-rouge">let x = null;</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">bigint</code></td>
      <td><code class="language-plaintext highlighter-rouge">123n</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">symbol</code></td>
      <td><code class="language-plaintext highlighter-rouge">Symbol("id")</code></td>
    </tr>
  </tbody>
</table>

<p>A couple of things worth noting:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">number</code> includes special values <code class="language-plaintext highlighter-rouge">NaN</code> (not-a-number) and <code class="language-plaintext highlighter-rouge">Infinity</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">bigint</code> is for integers larger than <code class="language-plaintext highlighter-rouge">number</code> can safely hold — note the <code class="language-plaintext highlighter-rouge">n</code>
suffix.</li>
</ul>

<p>You check a value’s type with the <code class="language-plaintext highlighter-rouge">typeof</code> operator. A few worth remembering:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typeof</span> <span class="mi">42</span>           <span class="c1">// "number"</span>
<span class="k">typeof</span> <span class="dl">"</span><span class="s2">hello</span><span class="dl">"</span>      <span class="c1">// "string"</span>
<span class="k">typeof</span> <span class="kc">true</span>         <span class="c1">// "boolean"</span>
<span class="k">typeof</span> <span class="kc">undefined</span>    <span class="c1">// "undefined"</span>
<span class="k">typeof</span> <span class="kc">null</span>         <span class="c1">// "object"   &lt;-- historical bug</span>
<span class="k">typeof</span> <span class="p">{}</span>           <span class="c1">// "object"</span>
<span class="k">typeof</span> <span class="p">[]</span>           <span class="c1">// "object"</span>
<span class="k">typeof</span> <span class="kd">function</span><span class="p">(){}</span> <span class="c1">// "function"</span>
</code></pre></div></div>

<p>Two gotchas to note: <code class="language-plaintext highlighter-rouge">typeof null</code> returns <code class="language-plaintext highlighter-rouge">"object"</code> (a long-standing bug in
the language), and arrays also report <code class="language-plaintext highlighter-rouge">"object"</code>.</p>

<p>For arrays specifically, use <code class="language-plaintext highlighter-rouge">Array.isArray(obj)</code>. Your instinct might be to
reach for <code class="language-plaintext highlighter-rouge">typeof</code>, but there’s a gotcha — both arrays and plain objects report
<code class="language-plaintext highlighter-rouge">"object"</code>, so <code class="language-plaintext highlighter-rouge">typeof</code> can’t tell them apart:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typeof</span> <span class="p">[]</span>   <span class="c1">// "object"</span>
<span class="k">typeof</span> <span class="p">{}</span>   <span class="c1">// "object"</span>

<span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">([])</span>   <span class="c1">// true</span>
<span class="nb">Array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">({})</span>   <span class="c1">// false</span>
</code></pre></div></div>

<h2 id="math-utilities">Math utilities</h2>

<p>The built-in <code class="language-plaintext highlighter-rouge">Math</code> object has the usual helpers. <code class="language-plaintext highlighter-rouge">Math.min</code> and <code class="language-plaintext highlighter-rouge">Math.max</code>
return the smallest/largest of their arguments, and <code class="language-plaintext highlighter-rouge">Infinity</code> is handy as a
starting “very large” value (for example when finding a minimum):</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Math</span><span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>   <span class="c1">// 1</span>
<span class="nb">Math</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>   <span class="c1">// 3</span>

<span class="kd">let</span> <span class="nx">smallest</span> <span class="o">=</span> <span class="kc">Infinity</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">x</span> <span class="k">of</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">])</span> <span class="p">{</span>
    <span class="nx">smallest</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="nx">smallest</span><span class="p">,</span> <span class="nx">x</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// smallest === 2</span>
</code></pre></div></div>

<h2 id="always-use--never-">Always use <code class="language-plaintext highlighter-rouge">===</code>, never <code class="language-plaintext highlighter-rouge">==</code></h2>

<p>This is the single most important habit to build. The honest answer is that
most modern JavaScript developers rarely use <code class="language-plaintext highlighter-rouge">==</code>.</p>

<p>Historically, <code class="language-plaintext highlighter-rouge">==</code> was added to make JavaScript more forgiving in the early days
of the web. It does <em>type coercion</em> before comparing, so it converts the
operands to a common type first:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">5</span><span class="dl">"</span> <span class="o">==</span> <span class="mi">5</span>      <span class="c1">// true</span>
<span class="mi">1</span> <span class="o">==</span> <span class="kc">true</span>     <span class="c1">// true</span>
<span class="mi">0</span> <span class="o">==</span> <span class="kc">false</span>    <span class="c1">// true</span>
</code></pre></div></div>

<p>The idea was that developers wouldn’t have to manually convert types all the
time. For example, a value coming from an HTML form is always a string:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">age</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">25</span><span class="dl">"</span><span class="p">;</span> <span class="c1">// from an HTML form</span>

<span class="k">if</span> <span class="p">(</span><span class="nx">age</span> <span class="o">==</span> <span class="mi">25</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">same</span><span class="dl">"</span><span class="p">);</span>   <span class="c1">// this prints</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The problem is that these coercion rules are surprising and error-prone. <code class="language-plaintext highlighter-rouge">===</code>
(strict equality) compares <strong>value and type</strong> with no coercion:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">5</span><span class="dl">"</span> <span class="o">===</span> <span class="mi">5</span>     <span class="c1">// false</span>
<span class="mi">1</span> <span class="o">===</span> <span class="kc">true</span>    <span class="c1">// false</span>
<span class="mi">0</span> <span class="o">===</span> <span class="kc">false</span>   <span class="c1">// false</span>
</code></pre></div></div>

<p><strong>Rule of thumb:</strong> always use <code class="language-plaintext highlighter-rouge">===</code> and <code class="language-plaintext highlighter-rouge">!==</code>. Forget <code class="language-plaintext highlighter-rouge">==</code> exists.</p>

<h2 id="declaring-variables-const-and-let">Declaring variables: <code class="language-plaintext highlighter-rouge">const</code> and <code class="language-plaintext highlighter-rouge">let</code></h2>

<p>Prefer <code class="language-plaintext highlighter-rouge">const</code> for anything that won’t be reassigned (think <code class="language-plaintext highlighter-rouge">final</code> in Java),
and <code class="language-plaintext highlighter-rouge">let</code> when you genuinely need to reassign. Avoid the old <code class="language-plaintext highlighter-rouge">var</code>.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">name</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Seroze</span><span class="dl">"</span><span class="p">;</span>   <span class="c1">// cannot be reassigned</span>
<span class="kd">let</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>           <span class="c1">// can be reassigned</span>
<span class="nx">count</span> <span class="o">=</span> <span class="nx">count</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>

<p><span style="color:red">Watch out: if you assign to a variable <em>without</em>
declaring it with <code class="language-plaintext highlighter-rouge">let</code>/<code class="language-plaintext highlighter-rouge">const</code>/<code class="language-plaintext highlighter-rouge">var</code>, JavaScript silently creates a <strong>global
variable</strong> instead of erroring. This is a historical quirk and a real source of
bugs.</span></p>

<p>I got bitten by this in a binary search — I used <code class="language-plaintext highlighter-rouge">lo</code> and <code class="language-plaintext highlighter-rouge">hi</code> without declaring
them, so they leaked into the global scope and the code did all sorts of garbage:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">search</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">target</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">lo</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>              <span class="c1">// ❌ no let/const — becomes a global!</span>
    <span class="nx">hi</span> <span class="o">=</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
    <span class="k">while</span> <span class="p">(</span><span class="nx">lo</span> <span class="o">&lt;=</span> <span class="nx">hi</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// ...</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The fix is just to declare them: <code class="language-plaintext highlighter-rouge">let lo = 0, hi = arr.length - 1;</code>. (Running in
<em>strict mode</em> — <code class="language-plaintext highlighter-rouge">"use strict";</code> — turns this silent footgun into an actual
error, which is why modules and classes enable it by default.)</p>

<h2 id="for-loops">For loops</h2>

<p>The classic C-style loop is exactly what you’d expect:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<h2 id="arrays">Arrays</h2>

<p>Arrays are JavaScript’s lists. Use <code class="language-plaintext highlighter-rouge">.length</code> to get the number of elements:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">];</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>   <span class="c1">// 3</span>

<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arr</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>A few array basics worth learning early: <code class="language-plaintext highlighter-rouge">push()</code> / <code class="language-plaintext highlighter-rouge">pop()</code> (add/remove at the
end), <code class="language-plaintext highlighter-rouge">shift()</code> / <code class="language-plaintext highlighter-rouge">unshift()</code> (front), <code class="language-plaintext highlighter-rouge">slice()</code>, <code class="language-plaintext highlighter-rouge">indexOf()</code>, and the
higher-order ones like <code class="language-plaintext highlighter-rouge">map()</code>, <code class="language-plaintext highlighter-rouge">filter()</code>, and <code class="language-plaintext highlighter-rouge">forEach()</code>.</p>

<h3 id="creating-an-array-of-size-n">Creating an array of size n</h3>

<p>Use the <code class="language-plaintext highlighter-rouge">Array(n)</code> constructor together with <code class="language-plaintext highlighter-rouge">.fill()</code> to get an array of a
fixed size with a default value:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">zeros</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Array</span><span class="p">(</span><span class="mi">5</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>     <span class="c1">// [0, 0, 0, 0, 0]</span>
<span class="kd">const</span> <span class="nx">ones</span>  <span class="o">=</span> <span class="k">new</span> <span class="nb">Array</span><span class="p">(</span><span class="mi">3</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>     <span class="c1">// [1, 1, 1]</span>
</code></pre></div></div>

<p>If you need each element computed from its index, use <code class="language-plaintext highlighter-rouge">Array.from()</code>:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// [0, 1, 2, 3, 4]</span>
<span class="kd">const</span> <span class="nx">seq</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="k">from</span><span class="p">({</span> <span class="na">length</span><span class="p">:</span> <span class="mi">5</span> <span class="p">},</span> <span class="p">(</span><span class="nx">_</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">i</span><span class="p">);</span>

<span class="c1">// 2D array (3x3 grid of zeros) — note: build each row separately</span>
<span class="kd">const</span> <span class="nx">grid</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">.</span><span class="k">from</span><span class="p">({</span> <span class="na">length</span><span class="p">:</span> <span class="mi">3</span> <span class="p">},</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="k">new</span> <span class="nb">Array</span><span class="p">(</span><span class="mi">3</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mi">0</span><span class="p">));</span>
</code></pre></div></div>

<blockquote>
  <p><strong>Heads up:</strong> don’t write <code class="language-plaintext highlighter-rouge">new Array(3).fill(new Array(3).fill(0))</code> for a 2D
grid — every row would be the <em>same</em> array reference, so changing one row
changes all of them. Use <code class="language-plaintext highlighter-rouge">Array.from</code> as shown above.</p>
</blockquote>

<h3 id="checking-if-an-element-is-in-an-array">Checking if an element is in an array</h3>

<p>Use <code class="language-plaintext highlighter-rouge">includes()</code> — it returns a boolean and is the cleanest way to check
membership:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">];</span>

<span class="nx">arr</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span>   <span class="c1">// true</span>
<span class="nx">arr</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="mi">99</span><span class="p">);</span>   <span class="c1">// false</span>
</code></pre></div></div>

<p>If you also need the <em>position</em> of the element, use <code class="language-plaintext highlighter-rouge">indexOf()</code>. It returns the
index, or <code class="language-plaintext highlighter-rouge">-1</code> if the element isn’t present:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">arr</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="mi">20</span><span class="p">);</span>    <span class="c1">// 1</span>
<span class="nx">arr</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="mi">99</span><span class="p">);</span>    <span class="c1">// -1</span>

<span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span> <span class="o">!==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">found it</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><span style="color:red">Note: <code class="language-plaintext highlighter-rouge">indexOf()</code> returns only the <strong>first</strong> matching
index, even if the value appears multiple times in the array.</span></p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">9</span><span class="p">].</span><span class="nx">indexOf</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span>   <span class="c1">// 0, not 2 — only the first match</span>
</code></pre></div></div>

<p>(If you need the last one, use <code class="language-plaintext highlighter-rouge">lastIndexOf()</code>.)</p>

<h3 id="sorting-always-pass-a-comparator">Sorting: always pass a comparator</h3>

<p>By default <code class="language-plaintext highlighter-rouge">sort()</code> converts elements to <strong>strings</strong> and sorts
lexicographically. This produces nonsense for numbers:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">];</span>

<span class="nx">nums</span><span class="p">.</span><span class="nx">sort</span><span class="p">();</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">nums</span><span class="p">);</span>   <span class="c1">// [1, 10, 2, 5]  ❌</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">10</code> comes before <code class="language-plaintext highlighter-rouge">2</code> because the string <code class="language-plaintext highlighter-rouge">"10"</code> is less than <code class="language-plaintext highlighter-rouge">"2"</code>.</p>

<p><span style="color:red">Always pass a custom comparator (a lambda) when sorting
numbers. The comparator returns a negative number if <code class="language-plaintext highlighter-rouge">a</code> should come first, zero
if equal, positive if <code class="language-plaintext highlighter-rouge">b</code> should come first.</span></p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">5</span><span class="p">];</span>

<span class="nx">nums</span><span class="p">.</span><span class="nx">sort</span><span class="p">((</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">a</span> <span class="o">-</span> <span class="nx">b</span><span class="p">);</span>   <span class="c1">// ascending</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">nums</span><span class="p">);</span>            <span class="c1">// [1, 2, 5, 10]  ✅</span>

<span class="nx">nums</span><span class="p">.</span><span class="nx">sort</span><span class="p">((</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">b</span> <span class="o">-</span> <span class="nx">a</span><span class="p">);</span>   <span class="c1">// descending</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">nums</span><span class="p">);</span>            <span class="c1">// [10, 5, 2, 1]</span>
</code></pre></div></div>

<p>Yes, the string-by-default behaviour is garbage — but this is how JavaScript
works, so just build the habit of always passing a comparator.</p>

<h4 id="comparator-vs-key-functions-vs-python">Comparator vs key functions (vs Python)</h4>

<p>There’s a subtle difference here if you’re coming from Python. <strong>JavaScript
follows the Java convention</strong> — <code class="language-plaintext highlighter-rouge">sort()</code> takes a <em>comparator</em> <code class="language-plaintext highlighter-rouge">(a, b)</code> that
answers <em>“which of these two comes first?”</em>. <strong>Python takes a <em>key</em> function</strong>
that answers <em>“what value should I sort this element by?”</em>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Python — key style
</span><span class="n">arr</span><span class="p">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">obj</span><span class="p">:</span> <span class="n">obj</span><span class="p">.</span><span class="n">x</span><span class="p">)</span>
</code></pre></div></div>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// JavaScript — comparator style</span>
<span class="nx">arr</span><span class="p">.</span><span class="nx">sort</span><span class="p">((</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">a</span><span class="p">.</span><span class="nx">x</span> <span class="o">-</span> <span class="nx">b</span><span class="p">.</span><span class="nx">x</span><span class="p">);</span>
</code></pre></div></div>

<p>A common mistake is to pass a Python-style key to JS: <code class="language-plaintext highlighter-rouge">arr.sort(o =&gt; o.x)</code>. That
silently breaks, because JS calls it as <code class="language-plaintext highlighter-rouge">fn(a, b)</code>, not <code class="language-plaintext highlighter-rouge">fn(a)</code>. To sort by a
key <code class="language-plaintext highlighter-rouge">fn</code>, wrap it in a comparator: <code class="language-plaintext highlighter-rouge">arr.sort((a, b) =&gt; fn(a) - fn(b))</code>.</p>

<h2 id="string-utility-methods">String utility methods</h2>

<p>Strings come with a bunch of built-in helpers. Get familiar with them — you’ll
reach for these constantly:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">s</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">hello world</span><span class="dl">"</span><span class="p">;</span>

<span class="nx">s</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>       <span class="c1">// "h"</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span>     <span class="c1">// "hello"</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">toUpperCase</span><span class="p">();</span>   <span class="c1">// "HELLO WORLD"</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">();</span>   <span class="c1">// "hello world"</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="dl">"</span><span class="s2">world</span><span class="dl">"</span><span class="p">)</span> <span class="c1">// 6</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">includes</span><span class="p">(</span><span class="dl">"</span><span class="s2">lo</span><span class="dl">"</span><span class="p">)</span>   <span class="c1">// true</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2"> </span><span class="dl">"</span><span class="p">);</span>      <span class="c1">// ["hello", "world"]</span>
<span class="nx">s</span><span class="p">.</span><span class="nx">trim</span><span class="p">();</span>          <span class="c1">// removes leading/trailing whitespace</span>
</code></pre></div></div>

<p>Note that <code class="language-plaintext highlighter-rouge">.length</code> works on strings too (<code class="language-plaintext highlighter-rouge">s.length</code> is <code class="language-plaintext highlighter-rouge">11</code>).</p>

<p>Strings in JavaScript are <strong>immutable</strong> — you can’t change a character in place.
Assigning to an index simply does nothing:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">s</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">hello</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">s</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">H</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>   <span class="c1">// "hello" — unchanged</span>
</code></pre></div></div>

<p>If you need to edit a string, convert it to a character array first, mutate the
array, then join it back:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">s</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">hello</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">chars</span> <span class="o">=</span> <span class="nx">s</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span>   <span class="c1">// ["h", "e", "l", "l", "o"]</span>
<span class="nx">chars</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">H</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">s</span> <span class="o">=</span> <span class="nx">chars</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span>          <span class="c1">// "Hello"</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">s</span><span class="p">);</span>              <span class="c1">// "Hello"</span>
</code></pre></div></div>

<p>The key trick is <code class="language-plaintext highlighter-rouge">const chars = s.split("")</code> — since strings are immutable, this
is the standard way to get a mutable char array you can index into and edit. It
comes up constantly in string problems, so keep it handy.</p>

<p>And to go back the other way, join the array into a string:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="nx">chars</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span>   <span class="c1">// convert char array back to a String</span>
</code></pre></div></div>

<h2 id="sets">Sets</h2>

<p>A <code class="language-plaintext highlighter-rouge">Set</code> stores unique values. Use <code class="language-plaintext highlighter-rouge">add()</code> to insert, <code class="language-plaintext highlighter-rouge">has()</code> to check
membership, <code class="language-plaintext highlighter-rouge">delete()</code> to remove, and <code class="language-plaintext highlighter-rouge">.size</code> for the count:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">seen</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Set</span><span class="p">();</span>
<span class="nx">seen</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="nx">seen</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="nx">seen</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">seen</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span> <span class="nx">seen</span><span class="p">.</span><span class="nx">size</span><span class="p">);</span>   <span class="c1">// true 2</span>
</code></pre></div></div>

<h2 id="the--spread--rest-operator">The <code class="language-plaintext highlighter-rouge">...</code> spread / rest operator</h2>

<p><code class="language-plaintext highlighter-rouge">...</code> is one of the most useful pieces of modern JS syntax. It does two
opposite-looking things depending on where it appears. (It’s roughly analogous
to Python’s <code class="language-plaintext highlighter-rouge">*args</code> / <code class="language-plaintext highlighter-rouge">*list</code> unpacking.)</p>

<h3 id="spread--unpack-into-individual-items">Spread — “unpack” into individual items</h3>

<p>It expands an array (or any iterable) into its individual elements. This is
exactly what <code class="language-plaintext highlighter-rouge">fn(...args)</code> does in the <code class="language-plaintext highlighter-rouge">cancellable</code> example above:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">fn</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span>   <span class="c1">// if args = [2, 3], this calls fn(2, 3)</span>
</code></pre></div></div>

<p>Other common uses:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>
<span class="kd">const</span> <span class="nx">b</span> <span class="o">=</span> <span class="p">[...</span><span class="nx">a</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">];</span>        <span class="c1">// [1, 2, 3, 4, 5]  — copy + extend</span>
<span class="nb">Math</span><span class="p">.</span><span class="nx">max</span><span class="p">(...</span><span class="nx">a</span><span class="p">);</span>                <span class="c1">// 3                — array -&gt; arguments</span>

<span class="kd">const</span> <span class="nx">o1</span> <span class="o">=</span> <span class="p">{</span> <span class="na">x</span><span class="p">:</span> <span class="mi">1</span> <span class="p">};</span>
<span class="kd">const</span> <span class="nx">o2</span> <span class="o">=</span> <span class="p">{</span> <span class="p">...</span><span class="nx">o1</span><span class="p">,</span> <span class="na">y</span><span class="p">:</span> <span class="mi">2</span> <span class="p">};</span>    <span class="c1">// { x: 1, y: 2 }   — works on objects too</span>
</code></pre></div></div>

<p>It’s also the idiomatic way to make a <strong>shallow copy</strong>: <code class="language-plaintext highlighter-rouge">const copy = [...arr]</code>.</p>

<p>Note that spread is only a <em>shallow</em> copy — nested objects/arrays are still
shared by reference. For a true <strong>deep copy</strong>, use the built-in
<code class="language-plaintext highlighter-rouge">structuredClone()</code>:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">original</span> <span class="o">=</span> <span class="p">{</span> <span class="na">a</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="na">nested</span><span class="p">:</span> <span class="p">{</span> <span class="na">b</span><span class="p">:</span> <span class="mi">2</span> <span class="p">}</span> <span class="p">};</span>

<span class="kd">const</span> <span class="nx">shallow</span> <span class="o">=</span> <span class="p">{</span> <span class="p">...</span><span class="nx">original</span> <span class="p">};</span>
<span class="nx">shallow</span><span class="p">.</span><span class="nx">nested</span><span class="p">.</span><span class="nx">b</span> <span class="o">=</span> <span class="mi">99</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">original</span><span class="p">.</span><span class="nx">nested</span><span class="p">.</span><span class="nx">b</span><span class="p">);</span>   <span class="c1">// 99  — nested object was shared ❌</span>

<span class="kd">const</span> <span class="nx">deep</span> <span class="o">=</span> <span class="nx">structuredClone</span><span class="p">(</span><span class="nx">original</span><span class="p">);</span>
<span class="nx">deep</span><span class="p">.</span><span class="nx">nested</span><span class="p">.</span><span class="nx">b</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">original</span><span class="p">.</span><span class="nx">nested</span><span class="p">.</span><span class="nx">b</span><span class="p">);</span>   <span class="c1">// 99  — original untouched ✅</span>
</code></pre></div></div>

<p>This is the JS equivalent of Python’s <code class="language-plaintext highlighter-rouge">copy.deepcopy()</code> (versus the shallow
<code class="language-plaintext highlighter-rouge">copy.copy()</code>).</p>

<h3 id="rest--collect-the-leftovers-into-one-array">Rest — “collect” the leftovers into one array</h3>

<p>In a function’s parameter list (or in destructuring), <code class="language-plaintext highlighter-rouge">...</code> does the reverse —
it gathers multiple values into a single array:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">sum</span><span class="p">(...</span><span class="nx">nums</span><span class="p">)</span> <span class="p">{</span>         <span class="c1">// nums is a real array</span>
    <span class="k">return</span> <span class="nx">nums</span><span class="p">.</span><span class="nx">reduce</span><span class="p">((</span><span class="nx">acc</span><span class="p">,</span> <span class="nx">x</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">acc</span> <span class="o">+</span> <span class="nx">x</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">sum</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span>                   <span class="c1">// 6</span>

<span class="kd">const</span> <span class="p">[</span><span class="nx">first</span><span class="p">,</span> <span class="p">...</span><span class="nx">others</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">];</span>
<span class="c1">// first = 10, others = [20, 30]</span>
</code></pre></div></div>

<p><strong>Rule of thumb:</strong> <code class="language-plaintext highlighter-rouge">...</code> in a <em>call or literal</em> spreads (unpacks); <code class="language-plaintext highlighter-rouge">...</code> in a
<em>parameter list or destructuring target</em> collects (rest).</p>

<h2 id="closures">Closures</h2>

<p>A <strong>closure</strong> is a function that “remembers” the variables from the scope where
it was created, even after that outer function has finished running. The inner
variable stays alive as long as the returned function holds a reference to it.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">create</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="nx">value</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>

    <span class="k">return</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
        <span class="nx">value</span> <span class="o">*=</span> <span class="mi">2</span><span class="p">;</span>
        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
    <span class="p">};</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">fn</span> <span class="o">=</span> <span class="nx">create</span><span class="p">();</span>

<span class="nx">fn</span><span class="p">();</span>   <span class="c1">// 10</span>
<span class="nx">fn</span><span class="p">();</span>   <span class="c1">// 20</span>
<span class="nx">fn</span><span class="p">();</span>   <span class="c1">// 40</span>
</code></pre></div></div>

<p>Even though <code class="language-plaintext highlighter-rouge">create()</code> has already returned, its <code class="language-plaintext highlighter-rouge">value</code> isn’t garbage-collected
— the returned arrow function keeps it alive and mutates it across calls. This is
the basis for things like counters, memoization, and private state.</p>

<p><strong>Analogy in Python:</strong> the exact same thing works, but reassigning the captured
variable needs the <code class="language-plaintext highlighter-rouge">nonlocal</code> keyword:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">create</span><span class="p">():</span>
    <span class="n">value</span> <span class="o">=</span> <span class="mi">5</span>
    <span class="k">def</span> <span class="nf">fn</span><span class="p">():</span>
        <span class="k">nonlocal</span> <span class="n">value</span>
        <span class="n">value</span> <span class="o">*=</span> <span class="mi">2</span>
        <span class="k">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">fn</span>
</code></pre></div></div>

<p><strong>Analogy in Java:</strong> Java has closures via lambdas/anonymous classes, but the
captured local variable must be <em>effectively final</em> — you cannot reassign it.
To get mutable state like above you’d capture a field or a one-element array
(<code class="language-plaintext highlighter-rouge">int[] value = {5};</code>).</p>

<h2 id="arrow-functions-and-this">Arrow functions and <code class="language-plaintext highlighter-rouge">this</code></h2>

<p>Arrow functions aren’t just shorter syntax for <code class="language-plaintext highlighter-rouge">function</code> — they differ in one
crucial way: <strong>an arrow function does not have its own <code class="language-plaintext highlighter-rouge">this</code>.</strong> It captures
<code class="language-plaintext highlighter-rouge">this</code> lexically, from the scope where it was <em>defined</em>. A regular <code class="language-plaintext highlighter-rouge">function</code>,
by contrast, gets its <code class="language-plaintext highlighter-rouge">this</code> rebound depending on <em>how it’s called</em>.</p>

<p>This wrinkle is the source of a classic pre-ES6 workaround. Look at this code:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">person</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Alice</span><span class="dl">"</span><span class="p">,</span>

    <span class="nx">greet</span><span class="p">()</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nb">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>

        <span class="kd">function</span> <span class="nx">fn</span><span class="p">()</span> <span class="p">{</span>
            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">self</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="nx">fn</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="nx">person</span><span class="p">.</span><span class="nx">greet</span><span class="p">();</span>   <span class="c1">// "Alice"</span>
</code></pre></div></div>

<p><strong>Why the <code class="language-plaintext highlighter-rouge">self = this</code> maneuver?</strong> Inside <code class="language-plaintext highlighter-rouge">greet()</code>, <code class="language-plaintext highlighter-rouge">this</code> correctly refers to
<code class="language-plaintext highlighter-rouge">person</code> (because it was called as <code class="language-plaintext highlighter-rouge">person.greet()</code>). But <code class="language-plaintext highlighter-rouge">fn</code> is a plain
<em>function</em>, not a method — so when it’s invoked as a bare <code class="language-plaintext highlighter-rouge">fn()</code>, JavaScript
rebinds its <code class="language-plaintext highlighter-rouge">this</code> to <code class="language-plaintext highlighter-rouge">undefined</code> (in strict mode) or the global object (in
sloppy mode). It is <strong>not</strong> <code class="language-plaintext highlighter-rouge">person</code>. So <code class="language-plaintext highlighter-rouge">this.name</code> inside <code class="language-plaintext highlighter-rouge">fn</code> would blow up or
print <code class="language-plaintext highlighter-rouge">undefined</code>.</p>

<p>The old fix: capture the <em>outer</em> <code class="language-plaintext highlighter-rouge">this</code> into an ordinary variable (<code class="language-plaintext highlighter-rouge">self</code>, often
called <code class="language-plaintext highlighter-rouge">that</code> or <code class="language-plaintext highlighter-rouge">_this</code>) while you still have the right value, then close over
that variable from the inner function. Closures behave predictably; <code class="language-plaintext highlighter-rouge">this</code>
doesn’t. So you sidestep <code class="language-plaintext highlighter-rouge">this</code> entirely.</p>

<p><strong>Arrow functions make this trick obsolete.</strong> Because an arrow function inherits
<code class="language-plaintext highlighter-rouge">this</code> from its surrounding scope, you can drop <code class="language-plaintext highlighter-rouge">self</code> completely:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">person</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Alice</span><span class="dl">"</span><span class="p">,</span>

    <span class="nx">greet</span><span class="p">()</span> <span class="p">{</span>
        <span class="kd">const</span> <span class="nx">fn</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
            <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>   <span class="c1">// `this` is still `person`</span>
        <span class="p">};</span>

        <span class="nx">fn</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">};</span>

<span class="nx">person</span><span class="p">.</span><span class="nx">greet</span><span class="p">();</span>   <span class="c1">// "Alice"</span>
</code></pre></div></div>

<p>The arrow function doesn’t get its own <code class="language-plaintext highlighter-rouge">this</code>, so <code class="language-plaintext highlighter-rouge">this</code> inside it is the same
<code class="language-plaintext highlighter-rouge">this</code> as in <code class="language-plaintext highlighter-rouge">greet</code> — which is <code class="language-plaintext highlighter-rouge">person</code>. No <code class="language-plaintext highlighter-rouge">self</code>, no <code class="language-plaintext highlighter-rouge">bind</code>, no surprises.
This is exactly why you’ll see arrows used for callbacks (<code class="language-plaintext highlighter-rouge">setTimeout</code>,
<code class="language-plaintext highlighter-rouge">.map</code>, event handlers, promises) — they keep <code class="language-plaintext highlighter-rouge">this</code> pointing at whatever the
enclosing method’s <code class="language-plaintext highlighter-rouge">this</code> was.</p>

<blockquote>
  <p>One consequence of the same rule: never use an arrow function <em>as</em> a method
when you need <code class="language-plaintext highlighter-rouge">this</code> to be the object. <code class="language-plaintext highlighter-rouge">greet: () =&gt; this.name</code> would capture
<code class="language-plaintext highlighter-rouge">this</code> from the module/global scope, not <code class="language-plaintext highlighter-rouge">person</code>. Use the <code class="language-plaintext highlighter-rouge">greet() { ... }</code>
shorthand (or a regular <code class="language-plaintext highlighter-rouge">function</code>) for methods, and arrows for the callbacks
inside them.</p>
</blockquote>

<p><strong>Analogy in Python:</strong> Python never had this footgun because methods take an
explicit <code class="language-plaintext highlighter-rouge">self</code> parameter — the binding is in the signature, not in how you call
the function. A nested function in Python simply closes over <code class="language-plaintext highlighter-rouge">self</code> like any
other variable:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Person</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">"Alice"</span>

    <span class="k">def</span> <span class="nf">greet</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">def</span> <span class="nf">fn</span><span class="p">():</span>
            <span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>   <span class="c1"># plain closure over `self`
</span>        <span class="n">fn</span><span class="p">()</span>
</code></pre></div></div>

<p>The JavaScript <code class="language-plaintext highlighter-rouge">const self = this</code> line is essentially a manual re-creation of
what Python gives you for free. This connects to [[blog-python-analogies]] —
JS’s <code class="language-plaintext highlighter-rouge">this</code> is the implicit, call-site-dependent version of Python’s explicit
<code class="language-plaintext highlighter-rouge">self</code>.</p>

<h2 id="generators">Generators</h2>

<p>A generator is a function that can pause and resume, producing a sequence of
values lazily — much like Python’s generators. You declare one with <code class="language-plaintext highlighter-rouge">function*</code>
and emit values with <code class="language-plaintext highlighter-rouge">yield</code>. Calling the generator returns an iterator, and
each <code class="language-plaintext highlighter-rouge">.next()</code> runs until the next <code class="language-plaintext highlighter-rouge">yield</code>.</p>

<p>Here’s an infinite Fibonacci generator:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span><span class="o">*</span> <span class="nx">fibonacci</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">let</span> <span class="p">[</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">];</span>
    <span class="k">while</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">yield</span> <span class="nx">a</span><span class="p">;</span>
        <span class="p">[</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">b</span><span class="p">,</span> <span class="nx">a</span> <span class="o">+</span> <span class="nx">b</span><span class="p">];</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">gen</span> <span class="o">=</span> <span class="nx">fibonacci</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">gen</span><span class="p">.</span><span class="nx">next</span><span class="p">().</span><span class="nx">value</span><span class="p">);</span>   <span class="c1">// 0</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">gen</span><span class="p">.</span><span class="nx">next</span><span class="p">().</span><span class="nx">value</span><span class="p">);</span>   <span class="c1">// 1</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">gen</span><span class="p">.</span><span class="nx">next</span><span class="p">().</span><span class="nx">value</span><span class="p">);</span>   <span class="c1">// 1</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">gen</span><span class="p">.</span><span class="nx">next</span><span class="p">().</span><span class="nx">value</span><span class="p">);</span>   <span class="c1">// 2</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">gen</span><span class="p">.</span><span class="nx">next</span><span class="p">().</span><span class="nx">value</span><span class="p">);</span>   <span class="c1">// 3</span>
</code></pre></div></div>

<p>Because it’s lazy, an infinite generator is fine — you just take as many values
as you need. For example, the first 10 Fibonacci numbers:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">firstN</span><span class="p">(</span><span class="nx">gen</span><span class="p">,</span> <span class="nx">n</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">out</span> <span class="o">=</span> <span class="p">[];</span>
    <span class="k">for</span> <span class="p">(</span><span class="kd">const</span> <span class="nx">x</span> <span class="k">of</span> <span class="nx">gen</span><span class="p">)</span> <span class="p">{</span>
        <span class="nx">out</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="nx">out</span><span class="p">.</span><span class="nx">length</span> <span class="o">===</span> <span class="nx">n</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nx">out</span><span class="p">;</span>
<span class="p">}</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">firstN</span><span class="p">(</span><span class="nx">fibonacci</span><span class="p">(),</span> <span class="mi">10</span><span class="p">));</span>
<span class="c1">// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]</span>
</code></pre></div></div>

<h2 id="objects">Objects</h2>

<p>In JavaScript you <strong>don’t need an explicit class declaration to make an object.</strong>
An object is just a bag of key-value pairs — essentially a hashmap with string
(or symbol) keys. You write one with braces, and you can read, add, or delete
keys at will:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">user</span> <span class="o">=</span> <span class="p">{</span>
    <span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Alice</span><span class="dl">"</span><span class="p">,</span>
    <span class="na">age</span><span class="p">:</span> <span class="mi">30</span><span class="p">,</span>
<span class="p">};</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">user</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>     <span class="c1">// "Alice"  — dot access</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">user</span><span class="p">[</span><span class="dl">"</span><span class="s2">age</span><span class="dl">"</span><span class="p">]);</span>   <span class="c1">// 30        — bracket access, like a hashmap</span>
<span class="nx">user</span><span class="p">.</span><span class="nx">email</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">a@x.com</span><span class="dl">"</span><span class="p">;</span>     <span class="c1">// add a key on the fly</span>
<span class="k">delete</span> <span class="nx">user</span><span class="p">.</span><span class="nx">age</span><span class="p">;</span>            <span class="c1">// remove one</span>
</code></pre></div></div>

<p>This is the same mental model as a Python <code class="language-plaintext highlighter-rouge">dict</code> — except the <code class="language-plaintext highlighter-rouge">.key</code> dot syntax
is first-class, and the keys are unordered string properties rather than
arbitrary hashable objects.</p>

<p><strong>Functions are special objects.</strong> A function in JS <em>is</em> an object that happens
to be callable — which means you can hang arbitrary properties off it, exactly
like any other object:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">hello</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">hello</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">hello</span><span class="p">);</span>   <span class="c1">// "function"</span>

<span class="nx">hello</span><span class="p">.</span><span class="nx">myProperty</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">hello</span><span class="p">.</span><span class="nx">myProperty</span><span class="p">);</span>   <span class="c1">// 42</span>
</code></pre></div></div>

<p>That last bit is perfectly valid JavaScript. The function still runs as a
function, but it also carries the <code class="language-plaintext highlighter-rouge">myProperty</code> field. This is why things like
memoization caches or static-style counters are sometimes stashed directly on
the function object.</p>

<p><strong>Where do <code class="language-plaintext highlighter-rouge">prototype</code> and <code class="language-plaintext highlighter-rouge">class</code> fit?</strong> Because objects are just hashmaps,
JavaScript originally had no real classes — shared behaviour was wired up through
the <strong>prototype</strong> chain. You can think of a prototype as roughly the equivalent
of an <strong>interface (or shared base) in Java</strong>: it’s the object that supplies the
methods every instance inherits. Modern JavaScript adds the <code class="language-plaintext highlighter-rouge">class</code> keyword,
which gives you familiar class syntax — but under the hood it’s still just
prototypes and objects:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nx">Animal</span> <span class="p">{</span>
    <span class="kd">constructor</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="nx">speak</span><span class="p">()</span> <span class="p">{</span>
        <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2"> makes a sound`</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Animal</span><span class="p">(</span><span class="dl">"</span><span class="s2">Rex</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">speak</span><span class="p">();</span>   <span class="c1">// "Rex makes a sound"</span>
</code></pre></div></div>

<p><strong>Analogy in Python:</strong> a plain JS object maps cleanly onto a Python <code class="language-plaintext highlighter-rouge">dict</code>, and
the <code class="language-plaintext highlighter-rouge">class</code> keyword onto a Python <code class="language-plaintext highlighter-rouge">class</code>. The difference is that Python keeps
“dict” and “class instance” as distinct concepts, whereas in JavaScript a class
instance <em>is</em> still an object/hashmap underneath — the line between data and
type is much blurrier.</p>

<h2 id="extending-built-ins-with-prototype">Extending built-ins with <code class="language-plaintext highlighter-rouge">.prototype</code></h2>

<p>In JavaScript you can add new methods to a built-in class (like <code class="language-plaintext highlighter-rouge">Array</code>) by
attaching them to its <code class="language-plaintext highlighter-rouge">prototype</code>. Every array then has access to your method:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">second</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span> <span class="mi">30</span><span class="p">];</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">second</span><span class="p">());</span>   <span class="c1">// 20</span>
</code></pre></div></div>

<p>This is real <strong>monkey-patching</strong> — you’re modifying the built-in type itself.</p>

<blockquote>
  <p><strong>Note:</strong> you <em>cannot</em> do this directly in Python. Python forbids patching
built-in types like <code class="language-plaintext highlighter-rouge">list</code> (<code class="language-plaintext highlighter-rouge">list.second = ...</code> raises a <code class="language-plaintext highlighter-rouge">TypeError</code>). To get
similar behaviour there you’d have to <strong>subclass</strong> <code class="language-plaintext highlighter-rouge">list</code>:</p>

  <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">MyList</span><span class="p">(</span><span class="nb">list</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">second</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
</code></pre></div>  </div>
</blockquote>

<p>A word of caution: monkey-patching built-ins is powerful but considered risky —
it affects <em>every</em> array in your program and can clash with future language
features or other libraries. Use it sparingly.</p>

<h2 id="settimeout-and-cleartimeout"><code class="language-plaintext highlighter-rouge">setTimeout</code> and <code class="language-plaintext highlighter-rouge">clearTimeout</code></h2>

<p><code class="language-plaintext highlighter-rouge">setTimeout(fn, t)</code> schedules <code class="language-plaintext highlighter-rouge">fn</code> to run once after <code class="language-plaintext highlighter-rouge">t</code> milliseconds. It
returns a <strong>timer id</strong> that you can pass to <code class="language-plaintext highlighter-rouge">clearTimeout(id)</code> to cancel the
call <em>before</em> it fires.</p>

<p>A classic LeetCode problem (<em>Cancellable Function</em>) makes this concrete: schedule
a function, but hand back a <code class="language-plaintext highlighter-rouge">cancel()</code> that stops it if called in time.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">cancellable</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">args</span><span class="p">,</span> <span class="nx">t</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">timerId</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">fn</span><span class="p">(...</span><span class="nx">args</span><span class="p">);</span> <span class="p">},</span> <span class="nx">t</span><span class="p">);</span>

    <span class="c1">// calling this before `t` ms have passed cancels the scheduled fn</span>
    <span class="k">return</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
        <span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timerId</span><span class="p">);</span>
    <span class="p">};</span>
<span class="p">};</span>
</code></pre></div></div>

<p>How it plays out: if the returned <code class="language-plaintext highlighter-rouge">cancel()</code> runs before <code class="language-plaintext highlighter-rouge">t</code>, <code class="language-plaintext highlighter-rouge">clearTimeout</code>
removes the pending call and <code class="language-plaintext highlighter-rouge">fn</code> never executes. If <code class="language-plaintext highlighter-rouge">t</code> elapses first, <code class="language-plaintext highlighter-rouge">fn</code>
runs and the later <code class="language-plaintext highlighter-rouge">clearTimeout</code> is a harmless no-op.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">fn</span> <span class="o">=</span> <span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">x</span> <span class="o">*</span> <span class="mi">5</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">args</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="nx">t</span> <span class="o">=</span> <span class="mi">20</span><span class="p">,</span> <span class="nx">cancelTimeMs</span> <span class="o">=</span> <span class="mi">50</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">cancel</span> <span class="o">=</span> <span class="nx">cancellable</span><span class="p">(</span><span class="nx">fn</span><span class="p">,</span> <span class="nx">args</span><span class="p">,</span> <span class="nx">t</span><span class="p">);</span>   <span class="c1">// fn fires at t = 20ms</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="nx">cancel</span><span class="p">,</span> <span class="nx">cancelTimeMs</span><span class="p">);</span>          <span class="c1">// cancel at 50ms — too late, fn already ran</span>
<span class="c1">// fn(2) returns 10</span>
</code></pre></div></div>

<p>Here <code class="language-plaintext highlighter-rouge">cancelTimeMs</code> (50) is greater than <code class="language-plaintext highlighter-rouge">t</code> (20), so <code class="language-plaintext highlighter-rouge">fn</code> fires first and the
cancel does nothing. If <code class="language-plaintext highlighter-rouge">cancelTimeMs</code> were less than <code class="language-plaintext highlighter-rouge">t</code>, the call would be
cancelled and <code class="language-plaintext highlighter-rouge">fn</code> would never run.</p>

<p>If the calling and execution flow is still confusing, here’s another way to
frame it:</p>

<ul>
  <li>You’re supposed to execute <code class="language-plaintext highlighter-rouge">fn</code> after a delay of <code class="language-plaintext highlighter-rouge">t</code>, and <em>also</em> return a
<code class="language-plaintext highlighter-rouge">cancel</code> function.</li>
  <li>If <code class="language-plaintext highlighter-rouge">cancel</code> is called, it should stop the pending timeout for <code class="language-plaintext highlighter-rouge">fn</code>.</li>
  <li>So if <code class="language-plaintext highlighter-rouge">cancel</code> is called <em>after</em> <code class="language-plaintext highlighter-rouge">fn</code> has already executed, nothing happens.
But if it’s called <em>before</em>, we clear the timeout so <code class="language-plaintext highlighter-rouge">fn</code> never runs at all.</li>
</ul>

<p>The implementation recipe is simple: put a <code class="language-plaintext highlighter-rouge">setTimeout</code> (which will resolve into
executing <code class="language-plaintext highlighter-rouge">fn</code>) just before returning the <code class="language-plaintext highlighter-rouge">cancel</code> function, and put a
<code class="language-plaintext highlighter-rouge">clearTimeout</code> inside <code class="language-plaintext highlighter-rouge">cancel</code>.</p>

<h3 id="setinterval-and-clearinterval"><code class="language-plaintext highlighter-rouge">setInterval</code> and <code class="language-plaintext highlighter-rouge">clearInterval</code></h3>

<p>Where <code class="language-plaintext highlighter-rouge">setTimeout</code> fires once, <code class="language-plaintext highlighter-rouge">setInterval(fn, t)</code> calls <code class="language-plaintext highlighter-rouge">fn</code> <strong>repeatedly</strong>
every <code class="language-plaintext highlighter-rouge">t</code> milliseconds. It also returns a timer id, which you cancel with
<code class="language-plaintext highlighter-rouge">clearInterval(id)</code> to stop the repeats:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">let</span> <span class="nx">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">setInterval</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">count</span><span class="o">++</span><span class="p">;</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">count</span><span class="p">);</span>
<span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>          <span class="c1">// logs 1, 2, 3, ... every second</span>

<span class="c1">// later, to stop it:</span>
<span class="nx">clearInterval</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span>
</code></pre></div></div>

<h2 id="the-event-loop-microtasks-vs-macrotasks">The event loop: microtasks vs macrotasks</h2>

<p>JavaScript is single-threaded, and async callbacks are scheduled onto two
different queues:</p>

<ul>
  <li><strong>Microtask queue</strong> — Promise callbacks (<code class="language-plaintext highlighter-rouge">.then</code>, <code class="language-plaintext highlighter-rouge">await</code>), <code class="language-plaintext highlighter-rouge">queueMicrotask</code>.</li>
  <li><strong>Macrotask queue</strong> — <code class="language-plaintext highlighter-rouge">setTimeout</code>, <code class="language-plaintext highlighter-rouge">setInterval</code>, I/O events.</li>
</ul>

<p>The event loop’s rule is simple but easy to get wrong:</p>

<ol>
  <li>Run <strong>all</strong> microtasks (draining the queue completely).</li>
  <li>Run <strong>one</strong> macrotask.</li>
  <li>Repeat.</li>
</ol>

<p>Crucially, the entire microtask queue is emptied before the <em>next</em> macrotask
runs — so a <code class="language-plaintext highlighter-rouge">setTimeout(fn, 0)</code> still waits behind every pending Promise
callback. Consider:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>

<span class="nx">setTimeout</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="p">},</span> <span class="mi">0</span><span class="p">);</span>

<span class="nb">Promise</span><span class="p">.</span><span class="nx">resolve</span><span class="p">()</span>
    <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> <span class="p">})</span>
    <span class="p">.</span><span class="nx">then</span><span class="p">(()</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span> <span class="p">});</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span>
</code></pre></div></div>

<p>This prints <strong><code class="language-plaintext highlighter-rouge">1, 5, 3, 4, 2</code></strong>:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">1</code> and <code class="language-plaintext highlighter-rouge">5</code> are synchronous — they run first, top to bottom.</li>
  <li><code class="language-plaintext highlighter-rouge">3</code> and <code class="language-plaintext highlighter-rouge">4</code> are microtasks (Promise callbacks) — they drain next, in order.</li>
  <li><code class="language-plaintext highlighter-rouge">2</code> is a macrotask (<code class="language-plaintext highlighter-rouge">setTimeout</code>) — even with a <code class="language-plaintext highlighter-rouge">0</code>ms delay, it runs <em>last</em>,
after the microtask queue is empty.</li>
</ul>

<p>(Python’s <code class="language-plaintext highlighter-rouge">asyncio</code> has a comparable distinction between ready callbacks and
scheduled-later ones, though the exact ordering rules differ.)</p>

<h2 id="valueof-and-tostring--custom-conversion"><code class="language-plaintext highlighter-rouge">valueOf()</code> and <code class="language-plaintext highlighter-rouge">toString()</code> — custom conversion</h2>

<p>JavaScript objects can control how they behave when converted to a number or a
string. This is something I ran into while solving LeetCode.</p>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">valueOf()</code></strong> is called when JavaScript needs a <em>numeric</em> value from an
object (for example, with the <code class="language-plaintext highlighter-rouge">+</code> operator).</li>
  <li><strong><code class="language-plaintext highlighter-rouge">toString()</code></strong> is called when it needs a <em>string</em> representation (for
example, inside <code class="language-plaintext highlighter-rouge">String(...)</code>).</li>
</ul>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nx">Box</span> <span class="p">{</span>
    <span class="kd">constructor</span><span class="p">(</span><span class="nx">x</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">x</span> <span class="o">=</span> <span class="nx">x</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="nx">valueOf</span><span class="p">()</span>  <span class="p">{</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">;</span> <span class="p">}</span>
    <span class="nx">toString</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="s2">`Box(</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">x</span><span class="p">}</span><span class="s2">)`</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>

<span class="kd">const</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="mi">7</span><span class="p">);</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span> <span class="o">+</span> <span class="nx">b</span><span class="p">);</span>        <span class="c1">// 10   -&gt; a.valueOf() + b.valueOf()</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">String</span><span class="p">(</span><span class="nx">a</span><span class="p">));</span>    <span class="c1">// "Box(3)" -&gt; a.toString()</span>
</code></pre></div></div>

<p>The LeetCode <strong>Array Wrapper</strong> problem uses both at once:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">ArrayWrapper</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">nums</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">nums</span> <span class="o">=</span> <span class="nx">nums</span><span class="p">;</span>
<span class="p">};</span>

<span class="nx">ArrayWrapper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">valueOf</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">nums</span><span class="p">.</span><span class="nx">reduce</span><span class="p">((</span><span class="nx">sum</span><span class="p">,</span> <span class="nx">x</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">sum</span> <span class="o">+</span> <span class="nx">x</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">};</span>

<span class="nx">ArrayWrapper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
    <span class="k">return</span> <span class="s2">`[</span><span class="p">${</span><span class="k">this</span><span class="p">.</span><span class="nx">nums</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="dl">'</span><span class="s1">,</span><span class="dl">'</span><span class="p">)}</span><span class="s2">]`</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">const</span> <span class="nx">obj1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ArrayWrapper</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]);</span>
<span class="kd">const</span> <span class="nx">obj2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ArrayWrapper</span><span class="p">([</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]);</span>

<span class="nx">obj1</span> <span class="o">+</span> <span class="nx">obj2</span><span class="p">;</span>     <span class="c1">// 10        -&gt; obj1.valueOf() + obj2.valueOf()</span>
<span class="nb">String</span><span class="p">(</span><span class="nx">obj1</span><span class="p">);</span>    <span class="c1">// "[1,2]"   -&gt; obj1.toString()</span>
</code></pre></div></div>

<p>This lets operators like <code class="language-plaintext highlighter-rouge">+</code> and functions like <code class="language-plaintext highlighter-rouge">String()</code> work naturally with
your own classes — a feature without a direct equivalent in Python, Java, or Go.</p>

<h2 id="takeaways">Takeaways</h2>

<ul>
  <li>Dynamic typing like Python, C-style syntax like Java.</li>
  <li>Always use <code class="language-plaintext highlighter-rouge">===</code> (and <code class="language-plaintext highlighter-rouge">!==</code>); ignore <code class="language-plaintext highlighter-rouge">==</code>.</li>
  <li>Use <code class="language-plaintext highlighter-rouge">const</code> by default, <code class="language-plaintext highlighter-rouge">let</code> when you must reassign.</li>
  <li>Learn the array basics and the common string methods — they cover most
day-to-day work.</li>
  <li>Always pass a comparator to <code class="language-plaintext highlighter-rouge">sort()</code> for numbers — the default sorts as
strings.</li>
  <li>Generators (<code class="language-plaintext highlighter-rouge">function*</code> / <code class="language-plaintext highlighter-rouge">yield</code>) give you lazy sequences.</li>
  <li>You can monkey-patch built-ins via <code class="language-plaintext highlighter-rouge">.prototype</code>, but do it sparingly.</li>
  <li>Custom classes can hook into <code class="language-plaintext highlighter-rouge">+</code> and <code class="language-plaintext highlighter-rouge">String()</code> via <code class="language-plaintext highlighter-rouge">valueOf()</code> and
<code class="language-plaintext highlighter-rouge">toString()</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">...</code> spreads in calls/literals and collects (rest) in parameter lists.</li>
</ul>]]></content><author><name>Seroze</name></author><category term="programming" /><category term="javascript" /><category term="web" /><category term="basics" /><summary type="html"><![CDATA[If you already know Python and Java, JavaScript is easy to pick up. It sits somewhere between the two:]]></summary></entry><entry><title type="html">Relearning HTML — The Building Blocks</title><link href="/html-basics/" rel="alternate" type="text/html" title="Relearning HTML — The Building Blocks" /><published>2026-06-20T18:30:00+00:00</published><updated>2026-06-20T18:30:00+00:00</updated><id>/html-basics</id><content type="html" xml:base="/html-basics/"><![CDATA[<p><em>I’m picking up HTML again from scratch. This post is my running set of notes on the fundamentals — the document skeleton, semantic elements, and the bits I keep forgetting.</em></p>

<hr />

<h2 id="the-document-skeleton">The document skeleton</h2>

<p>Every HTML page starts with the same boilerplate. It’s worth typing this out by hand a few times until it sticks:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">&lt;!DOCTYPE html&gt;</span>
<span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;head&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1.0"</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;title&gt;</span>My Page<span class="nt">&lt;/title&gt;</span>
  <span class="nt">&lt;/head&gt;</span>
  <span class="nt">&lt;body&gt;</span>
    <span class="nt">&lt;h1&gt;</span>Hello, world<span class="nt">&lt;/h1&gt;</span>
    <span class="nt">&lt;p&gt;</span>This is my first page.<span class="nt">&lt;/p&gt;</span>
  <span class="nt">&lt;/body&gt;</span>
<span class="nt">&lt;/html&gt;</span>
</code></pre></div></div>

<p>A few things I had to remind myself of:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">&lt;!DOCTYPE html&gt;</code> tells the browser to use standards mode. Without it you get “quirks mode” and old, inconsistent rendering.</li>
  <li><code class="language-plaintext highlighter-rouge">&lt;head&gt;</code> holds metadata — things the user doesn’t see directly (title, charset, links to CSS).</li>
  <li><code class="language-plaintext highlighter-rouge">&lt;body&gt;</code> is the visible content.</li>
  <li><code class="language-plaintext highlighter-rouge">lang="en"</code> and <code class="language-plaintext highlighter-rouge">charset="UTF-8"</code> matter for accessibility and correct character rendering.</li>
</ul>

<h2 id="semantic-elements">Semantic elements</h2>

<p>Instead of wrapping everything in <code class="language-plaintext highlighter-rouge">&lt;div&gt;</code>, HTML5 gives you tags that describe <em>meaning</em>. This helps screen readers, SEO, and your own sanity:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;header&gt;</span>Site title and nav<span class="nt">&lt;/header&gt;</span>
<span class="nt">&lt;nav&gt;</span>Links<span class="nt">&lt;/nav&gt;</span>
<span class="nt">&lt;main&gt;</span>
  <span class="nt">&lt;article&gt;</span>
    <span class="nt">&lt;h2&gt;</span>A blog post<span class="nt">&lt;/h2&gt;</span>
    <span class="nt">&lt;section&gt;</span>...<span class="nt">&lt;/section&gt;</span>
  <span class="nt">&lt;/article&gt;</span>
  <span class="nt">&lt;aside&gt;</span>Sidebar<span class="nt">&lt;/aside&gt;</span>
<span class="nt">&lt;/main&gt;</span>
<span class="nt">&lt;footer&gt;</span>Copyright<span class="nt">&lt;/footer&gt;</span>
</code></pre></div></div>

<p>Rule of thumb I’m trying to follow: reach for a semantic tag first, and only fall back to <code class="language-plaintext highlighter-rouge">&lt;div&gt;</code> when nothing else fits.</p>

<h2 id="text-basics">Text basics</h2>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;h1&gt;</span>–<span class="nt">&lt;h6&gt;</span>   <span class="c">&lt;!-- headings, in order of importance --&gt;</span>
<span class="nt">&lt;p&gt;</span>          <span class="c">&lt;!-- paragraph --&gt;</span>
<span class="nt">&lt;strong&gt;</span>     <span class="c">&lt;!-- important (bold) --&gt;</span>
<span class="nt">&lt;em&gt;</span>         <span class="c">&lt;!-- emphasis (italic) --&gt;</span>
<span class="nt">&lt;br</span> <span class="nt">/&gt;</span>       <span class="c">&lt;!-- line break --&gt;</span>
<span class="nt">&lt;hr</span> <span class="nt">/&gt;</span>       <span class="c">&lt;!-- thematic break --&gt;</span>
</code></pre></div></div>

<p>One thing that bit me: headings should follow a logical order (<code class="language-plaintext highlighter-rouge">h1</code> → <code class="language-plaintext highlighter-rouge">h2</code> → <code class="language-plaintext highlighter-rouge">h3</code>), not be chosen for their size. Sizing is a CSS concern.</p>

<h2 id="links-and-images">Links and images</h2>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"https://example.com"</span><span class="nt">&gt;</span>A link<span class="nt">&lt;/a&gt;</span>
<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"/about"</span><span class="nt">&gt;</span>An internal link<span class="nt">&lt;/a&gt;</span>

<span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"cat.jpg"</span> <span class="na">alt=</span><span class="s">"A sleepy cat"</span> <span class="nt">/&gt;</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">alt</code> text isn’t optional in my book — it’s what screen readers announce and what shows when the image fails to load.</p>

<h2 id="lists">Lists</h2>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;ul&gt;</span>
  <span class="nt">&lt;li&gt;</span>Unordered item<span class="nt">&lt;/li&gt;</span>
<span class="nt">&lt;/ul&gt;</span>

<span class="nt">&lt;ol&gt;</span>
  <span class="nt">&lt;li&gt;</span>Ordered item<span class="nt">&lt;/li&gt;</span>
<span class="nt">&lt;/ol&gt;</span>
</code></pre></div></div>

<h2 id="whats-next">What’s next</h2>

<p>Next I want to dig into <strong>forms</strong> (<code class="language-plaintext highlighter-rouge">&lt;input&gt;</code>, <code class="language-plaintext highlighter-rouge">&lt;label&gt;</code>, validation) and how HTML connects to CSS for layout. I’ll post those notes as I go.</p>]]></content><author><name>Seroze</name></author><category term="web" /><category term="html" /><category term="web" /><category term="frontend" /><summary type="html"><![CDATA[I’m picking up HTML again from scratch. This post is my running set of notes on the fundamentals — the document skeleton, semantic elements, and the bits I keep forgetting.]]></summary></entry><entry><title type="html">SSH Tunnelling — Forwarding Ports Over SSH</title><link href="/ssh-tunnelling/" rel="alternate" type="text/html" title="SSH Tunnelling — Forwarding Ports Over SSH" /><published>2026-06-20T18:30:00+00:00</published><updated>2026-06-20T18:30:00+00:00</updated><id>/ssh-tunnelling</id><content type="html" xml:base="/ssh-tunnelling/"><![CDATA[<p><em>I keep a dev server running on a remote Linux box but want to hit it from my laptop’s browser. SSH tunnelling solves this in one line. These are my notes on what the flags actually mean.</em></p>

<hr />

<h2 id="the-real-situation-that-led-me-here">The real situation that led me here</h2>

<p>I was relearning HTML, and my files lived on my <strong>Linux box</strong> — that’s where I was editing <code class="language-plaintext highlighter-rouge">test1.html</code> and friends. But I was actually working from my <strong>macOS machine</strong>. I wanted to preview the pages in my Mac’s browser without copying files back and forth.</p>

<p>The fix was simple:</p>

<ol>
  <li>
    <p>On the Linux box, in the directory holding the HTML files, I started a tiny web server:</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> ~/html-practice          <span class="c"># the folder with test1.html</span>
python3 <span class="nt">-m</span> http.server 8000
</code></pre></div>    </div>
  </li>
  <li>
    <p>On my Mac, I set up port forwarding so my Mac’s <code class="language-plaintext highlighter-rouge">localhost:8000</code> points at the Linux box’s <code class="language-plaintext highlighter-rouge">8000</code>:</p>

    <div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-L</span> 8000:localhost:8000 user@linux-host
</code></pre></div>    </div>
  </li>
  <li>
    <p>Then in my Mac’s browser I typed:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8000/test1.html
</code></pre></div>    </div>

    <p>…and the actual HTML page rendered. The browser is on my Mac, but the file and the server are on the Linux box, with everything flowing through the SSH tunnel. Very cool.</p>
  </li>
</ol>

<blockquote>
  <p><strong>Gotcha I hit:</strong> <code class="language-plaintext highlighter-rouge">python3 -m http.server</code> only serves files in the <strong>directory it was launched from</strong>. If I started it in my home folder but <code class="language-plaintext highlighter-rouge">test1.html</code> lived in <code class="language-plaintext highlighter-rouge">~/html-practice/</code>, the server couldn’t see it and I got a 404. Always <code class="language-plaintext highlighter-rouge">cd</code> into the folder with your files <em>before</em> starting <code class="language-plaintext highlighter-rouge">http.server</code> (or pass <code class="language-plaintext highlighter-rouge">--directory</code>).</p>
</blockquote>

<hr />

<h2 id="the-one-liner">The one-liner</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-L</span> 8000:localhost:8000 youruser@linux-machine
</code></pre></div></div>

<p>After running this, opening <code class="language-plaintext highlighter-rouge">http://localhost:8000</code> in my <strong>laptop’s</strong> browser actually reaches a service listening on port <code class="language-plaintext highlighter-rouge">8000</code> of the <strong>remote</strong> <code class="language-plaintext highlighter-rouge">linux-machine</code>. The traffic rides inside the encrypted SSH connection.</p>

<h2 id="reading-the--l-flag">Reading the <code class="language-plaintext highlighter-rouge">-L</code> flag</h2>

<p><code class="language-plaintext highlighter-rouge">-L</code> means <strong>local port forwarding</strong>. The argument has three parts separated by colons:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-L  [local_port] : [target_host] : [target_port]
        8000      :   localhost   :    8000
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">8000</code> (first) — the port to open <strong>on my laptop</strong> (the SSH client side).</li>
  <li><code class="language-plaintext highlighter-rouge">localhost</code> — the host to connect to, <strong>as seen from the remote machine</strong>. This is the key subtlety: <code class="language-plaintext highlighter-rouge">localhost</code> here is the remote box’s own loopback, not my laptop’s.</li>
  <li><code class="language-plaintext highlighter-rouge">8000</code> (second) — the port on that target host.</li>
</ul>

<p>So “take connections to <code class="language-plaintext highlighter-rouge">localhost:8000</code> on my laptop, send them through the SSH tunnel, and on the far end connect to <code class="language-plaintext highlighter-rouge">localhost:8000</code>.”</p>

<h2 id="why-localhost-refers-to-the-remote-machine">Why <code class="language-plaintext highlighter-rouge">localhost</code> refers to the remote machine</h2>

<p>This trips people up. The <code class="language-plaintext highlighter-rouge">target_host:target_port</code> part is resolved <strong>from the remote machine’s perspective</strong>, because that’s where the tunnel exits. You can forward to other hosts the remote can reach, too:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Reach a database that only the remote machine can see</span>
ssh <span class="nt">-L</span> 5432:db.internal:5432 youruser@linux-machine
</code></pre></div></div>

<p>Here <code class="language-plaintext highlighter-rouge">db.internal</code> is resolved by <code class="language-plaintext highlighter-rouge">linux-machine</code>, not by my laptop. This is how you tunnel to internal services behind a bastion host.</p>

<h2 id="local-vs-remote-forwarding">Local vs remote forwarding</h2>

<p>There are two directions, and mixing them up is the classic mistake:</p>

<table>
  <thead>
    <tr>
      <th>Flag</th>
      <th>Direction</th>
      <th>“Expose <em>__ to __</em>”</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">-L</code></td>
      <td>Local forwarding</td>
      <td>a <strong>remote</strong> service → my <strong>local</strong> machine</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">-R</code></td>
      <td>Remote forwarding</td>
      <td>a <strong>local</strong> service → the <strong>remote</strong> machine</td>
    </tr>
  </tbody>
</table>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># -L: I want to reach the remote's port 8000 from my laptop</span>
ssh <span class="nt">-L</span> 8000:localhost:8000 youruser@linux-machine

<span class="c"># -R: I want the remote to reach my laptop's port 3000</span>
ssh <span class="nt">-R</span> 3000:localhost:3000 youruser@linux-machine
</code></pre></div></div>

<h2 id="handy-extra-flags">Handy extra flags</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># -N : don't run a remote command, just hold the tunnel open</span>
<span class="c"># -f : background the SSH process after connecting</span>
ssh <span class="nt">-N</span> <span class="nt">-f</span> <span class="nt">-L</span> 8000:localhost:8000 youruser@linux-machine
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">-N -f</code> is what I use when I just want the tunnel and don’t need an interactive shell.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Bind the local end to all interfaces, not just loopback</span>
<span class="c"># (lets other machines on my LAN use the tunnel too)</span>
ssh <span class="nt">-L</span> 0.0.0.0:8000:localhost:8000 youruser@linux-machine
</code></pre></div></div>

<h2 id="tearing-it-down">Tearing it down</h2>

<p>If you backgrounded it with <code class="language-plaintext highlighter-rouge">-f</code>, find and kill it:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Find the tunnel</span>
ps aux | <span class="nb">grep</span> <span class="s2">"ssh -N"</span>

<span class="c"># or, if you forwarded a known port</span>
lsof <span class="nt">-i</span> :8000
<span class="nb">kill</span> &lt;pid&gt;
</code></pre></div></div>

<p>For a foreground tunnel, just <code class="language-plaintext highlighter-rouge">Ctrl-C</code> (or type <code class="language-plaintext highlighter-rouge">~.</code> to drop an SSH session).</p>

<h2 id="common-gotchas">Common gotchas</h2>

<ul>
  <li><strong>“Connection refused” on the remote side</strong> usually means nothing is actually listening on the target port on the remote machine. SSH the box and check with <code class="language-plaintext highlighter-rouge">ss -tlnp</code>.</li>
  <li><strong>Port already in use locally</strong> — pick a different local port: <code class="language-plaintext highlighter-rouge">-L 8001:localhost:8000</code>.</li>
  <li><strong>Service binds to <code class="language-plaintext highlighter-rouge">0.0.0.0</code> vs <code class="language-plaintext highlighter-rouge">127.0.0.1</code></strong> — if the remote service only listens on <code class="language-plaintext highlighter-rouge">127.0.0.1</code>, forwarding to <code class="language-plaintext highlighter-rouge">localhost</code> works fine. That’s the common case.</li>
</ul>

<hr />

<p>A single <code class="language-plaintext highlighter-rouge">ssh -L</code> line is one of those tools that feels like magic the first time it clicks — encrypted, no extra software, and it works through anything that lets SSH out.</p>]]></content><author><name>Seroze</name></author><category term="networking" /><category term="ssh" /><category term="networking" /><category term="tunnelling" /><category term="port-forwarding" /><summary type="html"><![CDATA[I keep a dev server running on a remote Linux box but want to hit it from my laptop’s browser. SSH tunnelling solves this in one line. These are my notes on what the flags actually mean.]]></summary></entry><entry><title type="html">Backtracking — The Art of Systematic Undoing</title><link href="/backtracking/" rel="alternate" type="text/html" title="Backtracking — The Art of Systematic Undoing" /><published>2026-06-19T18:30:00+00:00</published><updated>2026-06-19T18:30:00+00:00</updated><id>/backtracking</id><content type="html" xml:base="/backtracking/"><![CDATA[<p><em>Backtracking is just DFS on a decision tree — at each node you make a choice, recurse into it, and undo the choice before trying the next one.</em></p>

<hr />

<h2 id="the-core-idea">The core idea</h2>

<p>Every backtracking problem can be modeled as a tree where:</p>

<ul>
  <li>Each <strong>node</strong> is a partial state (decisions made so far).</li>
  <li>Each <strong>edge</strong> is a single choice extending that state.</li>
  <li><strong>Leaves</strong> are either valid complete solutions or dead ends.</li>
</ul>

<p>Backtracking = exhaustive search with early termination. You explore the tree depth-first, and whenever a partial state can’t lead to any valid solution, you <strong>prune</strong> the branch and backtrack to the parent.</p>

<p>The universal template:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">backtrack</span><span class="p">(</span><span class="n">State</span><span class="o">&amp;</span> <span class="n">state</span><span class="p">,</span> <span class="n">Choices</span><span class="o">&amp;</span> <span class="n">available</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">is_solution</span><span class="p">(</span><span class="n">state</span><span class="p">))</span> <span class="p">{</span>
        <span class="n">record</span><span class="p">(</span><span class="n">state</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">for</span> <span class="p">(</span><span class="n">Choice</span> <span class="n">c</span> <span class="o">:</span> <span class="n">available</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">is_valid</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">c</span><span class="p">))</span> <span class="k">continue</span><span class="p">;</span>   <span class="c1">// prune</span>

        <span class="n">apply</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>                      <span class="c1">// choose</span>
        <span class="n">backtrack</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">available</span><span class="p">);</span>          <span class="c1">// explore</span>
        <span class="n">undo</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">c</span><span class="p">);</span>                       <span class="c1">// unchoose</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The critical discipline: <strong>every <code class="language-plaintext highlighter-rouge">apply</code> must be mirrored by an <code class="language-plaintext highlighter-rouge">undo</code></strong>. If you forget to undo, choices from one branch bleed into siblings.</p>

<hr />

<h2 id="problem-1--subsets-power-set">Problem 1 — Subsets (power set)</h2>

<p>Generate all subsets of <code class="language-plaintext highlighter-rouge">[1, 2, 3, ..., n]</code>.</p>

<p>At each index <code class="language-plaintext highlighter-rouge">i</code>, make a binary choice: include <code class="language-plaintext highlighter-rouge">a[i]</code> or skip it.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">backtrack</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">i</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">current</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">current</span><span class="p">);</span>           <span class="c1">// every prefix is a valid subset</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">a</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">current</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>         <span class="c1">// choose a[j]</span>
        <span class="n">backtrack</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">current</span><span class="p">);</span>   <span class="c1">// explore subsets starting after j</span>
        <span class="n">current</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>              <span class="c1">// unchoose a[j]</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">subsets</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">current</span><span class="p">;</span>
    <span class="n">backtrack</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">current</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The loop iterates <code class="language-plaintext highlighter-rouge">j</code> from <code class="language-plaintext highlighter-rouge">i</code> forward (not from 0) to avoid counting the same subset twice in different orderings. There are \(2^n\) subsets, so time is \(O(2^n \cdot n)\) (copying each subset takes \(O(n)\)).</p>

<hr />

<h2 id="problem-2--permutations">Problem 2 — Permutations</h2>

<p>Generate all permutations of <code class="language-plaintext highlighter-rouge">n</code> distinct integers.</p>

<p>The trick: swap element <code class="language-plaintext highlighter-rouge">i</code> into position <code class="language-plaintext highlighter-rouge">start</code>, recurse on <code class="language-plaintext highlighter-rouge">[start+1, n)</code>, then swap back.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">backtrack</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">start</span> <span class="o">==</span> <span class="n">a</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span>
        <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">start</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>            <span class="c1">// place a[i] at position start</span>
        <span class="n">backtrack</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">start</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>            <span class="c1">// restore</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">permutations</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">a</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">backtrack</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>There are \(n!\) permutations, so time is \(O(n! \cdot n)\).</p>

<p><strong>Permutations with duplicates:</strong> sort first, then skip if <code class="language-plaintext highlighter-rouge">a[i] == a[start]</code> and <code class="language-plaintext highlighter-rouge">i != start</code> (same value was already placed at this position).</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="nf">backtrack</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">start</span> <span class="o">==</span> <span class="n">a</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="p">{</span> <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="k">return</span><span class="p">;</span> <span class="p">}</span>

    <span class="n">unordered_set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">seen</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">a</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">seen</span><span class="p">.</span><span class="n">count</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span> <span class="k">continue</span><span class="p">;</span>   <span class="c1">// same value placed here before</span>
        <span class="n">seen</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">start</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="n">backtrack</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
        <span class="n">swap</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">start</span><span class="p">],</span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h2 id="problem-3--combination-sum">Problem 3 — Combination Sum</h2>

<p>Given <code class="language-plaintext highlighter-rouge">candidates</code> (distinct positive integers) and a <code class="language-plaintext highlighter-rouge">target</code>, find all combinations that sum to <code class="language-plaintext highlighter-rouge">target</code>. You may use each number unlimited times.</p>

<p>The pruning key: sort first, then break early when <code class="language-plaintext highlighter-rouge">candidates[j] &gt; remaining</code>.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">backtrack</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">cands</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">remaining</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">current</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">remaining</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">current</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">cands</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">remaining</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>   <span class="c1">// sorted — no point continuing</span>

        <span class="n">current</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
        <span class="n">backtrack</span><span class="p">(</span><span class="n">cands</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">remaining</span> <span class="o">-</span> <span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">current</span><span class="p">);</span>  <span class="c1">// i, not i+1 (reuse allowed)</span>
        <span class="n">current</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&gt;</span> <span class="n">combinationSum</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">candidates</span><span class="p">,</span> <span class="kt">int</span> <span class="n">target</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">sort</span><span class="p">(</span><span class="n">candidates</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">candidates</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">current</span><span class="p">;</span>
    <span class="n">backtrack</span><span class="p">(</span><span class="n">candidates</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">current</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>For <strong>Combination Sum II</strong> (each element used once, may have duplicates): pass <code class="language-plaintext highlighter-rouge">i+1</code> and skip <code class="language-plaintext highlighter-rouge">cands[i] == cands[i-1]</code> at the same recursion depth.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">cands</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">&gt;</span> <span class="n">start</span> <span class="o">&amp;&amp;</span> <span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="k">continue</span><span class="p">;</span>  <span class="c1">// skip same value at same level</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">remaining</span><span class="p">)</span> <span class="k">break</span><span class="p">;</span>
    <span class="n">current</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
    <span class="n">backtrack</span><span class="p">(</span><span class="n">cands</span><span class="p">,</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">remaining</span> <span class="o">-</span> <span class="n">cands</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">current</span><span class="p">);</span>
    <span class="n">current</span><span class="p">.</span><span class="n">pop_back</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>

<hr />

<h2 id="problem-4--n-queens">Problem 4 — N-Queens</h2>

<p>Place <code class="language-plaintext highlighter-rouge">n</code> queens on an <code class="language-plaintext highlighter-rouge">n×n</code> board such that no two attack each other.</p>

<p>Constraint: no two queens share a column, row, or diagonal. Since we place one queen per row, rows are automatically distinct. Track forbidden columns and diagonals.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">n</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&gt;</span> <span class="n">result</span><span class="p">;</span>

<span class="c1">// col[c] = queen in column c</span>
<span class="c1">// diag1[r-c+n] = queen on major diagonal (r-c constant)</span>
<span class="c1">// diag2[r+c]   = queen on minor diagonal (r+c constant)</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span> <span class="n">col</span><span class="p">,</span> <span class="n">diag1</span><span class="p">,</span> <span class="n">diag2</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">backtrack</span><span class="p">(</span><span class="kt">int</span> <span class="n">row</span><span class="p">,</span> <span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&amp;</span> <span class="n">board</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">row</span> <span class="o">==</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
        <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">board</span><span class="p">);</span>
        <span class="k">return</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">c</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">;</span> <span class="n">c</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">col</span><span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="o">||</span> <span class="n">diag1</span><span class="p">[</span><span class="n">row</span> <span class="o">-</span> <span class="n">c</span> <span class="o">+</span> <span class="n">n</span><span class="p">]</span> <span class="o">||</span> <span class="n">diag2</span><span class="p">[</span><span class="n">row</span> <span class="o">+</span> <span class="n">c</span><span class="p">])</span> <span class="k">continue</span><span class="p">;</span>

        <span class="n">board</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'Q'</span><span class="p">;</span>
        <span class="n">col</span><span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">diag1</span><span class="p">[</span><span class="n">row</span> <span class="o">-</span> <span class="n">c</span> <span class="o">+</span> <span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">diag2</span><span class="p">[</span><span class="n">row</span> <span class="o">+</span> <span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>

        <span class="n">backtrack</span><span class="p">(</span><span class="n">row</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">board</span><span class="p">);</span>

        <span class="n">board</span><span class="p">[</span><span class="n">row</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'.'</span><span class="p">;</span>
        <span class="n">col</span><span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">diag1</span><span class="p">[</span><span class="n">row</span> <span class="o">-</span> <span class="n">c</span> <span class="o">+</span> <span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">diag2</span><span class="p">[</span><span class="n">row</span> <span class="o">+</span> <span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;&gt;</span> <span class="n">solveNQueens</span><span class="p">(</span><span class="kt">int</span> <span class="n">_n</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">n</span> <span class="o">=</span> <span class="n">_n</span><span class="p">;</span>
    <span class="n">col</span><span class="p">.</span><span class="n">assign</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
    <span class="n">diag1</span><span class="p">.</span><span class="n">assign</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">n</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
    <span class="n">diag2</span><span class="p">.</span><span class="n">assign</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">n</span><span class="p">,</span> <span class="nb">false</span><span class="p">);</span>
    <span class="n">vector</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">board</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">string</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="sc">'.'</span><span class="p">));</span>
    <span class="n">backtrack</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">board</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The diagonal indexing is the key insight:</p>
<ul>
  <li>Major diagonal: <code class="language-plaintext highlighter-rouge">r - c</code> is constant. Shift by <code class="language-plaintext highlighter-rouge">n</code> to avoid negatives: <code class="language-plaintext highlighter-rouge">r - c + n</code>.</li>
  <li>Minor diagonal: <code class="language-plaintext highlighter-rouge">r + c</code> is constant.</li>
</ul>

<p>This gives \(O(1)\) conflict checks instead of scanning the board each time.</p>

<hr />

<h2 id="problem-5--word-search-on-a-grid">Problem 5 — Word Search on a grid</h2>

<p>Given a 2D character grid and a word, determine whether the word exists as a connected path (horizontal/vertical, no cell reused).</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">rows</span><span class="p">,</span> <span class="n">cols</span><span class="p">;</span>
<span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&gt;</span> <span class="n">grid</span><span class="p">;</span>
<span class="n">string</span> <span class="n">word</span><span class="p">;</span>

<span class="kt">bool</span> <span class="nf">backtrack</span><span class="p">(</span><span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">c</span><span class="p">,</span> <span class="kt">int</span> <span class="n">idx</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">idx</span> <span class="o">==</span> <span class="n">word</span><span class="p">.</span><span class="n">size</span><span class="p">())</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">r</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">r</span> <span class="o">&gt;=</span> <span class="n">rows</span> <span class="o">||</span> <span class="n">c</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">c</span> <span class="o">&gt;=</span> <span class="n">cols</span><span class="p">)</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">!=</span> <span class="n">word</span><span class="p">[</span><span class="n">idx</span><span class="p">])</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>

    <span class="kt">char</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">];</span>
    <span class="n">grid</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'#'</span><span class="p">;</span>   <span class="c1">// mark visited</span>

    <span class="kt">bool</span> <span class="n">found</span> <span class="o">=</span> <span class="n">backtrack</span><span class="p">(</span><span class="n">r</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
              <span class="o">||</span> <span class="n">backtrack</span><span class="p">(</span><span class="n">r</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
              <span class="o">||</span> <span class="n">backtrack</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
              <span class="o">||</span> <span class="n">backtrack</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>

    <span class="n">grid</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>   <span class="c1">// restore</span>
    <span class="k">return</span> <span class="n">found</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">bool</span> <span class="n">exist</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&gt;&amp;</span> <span class="n">g</span><span class="p">,</span> <span class="n">string</span> <span class="n">w</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">grid</span> <span class="o">=</span> <span class="n">g</span><span class="p">;</span> <span class="n">word</span> <span class="o">=</span> <span class="n">w</span><span class="p">;</span>
    <span class="n">rows</span> <span class="o">=</span> <span class="n">g</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">cols</span> <span class="o">=</span> <span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">size</span><span class="p">();</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">r</span> <span class="o">&lt;</span> <span class="n">rows</span><span class="p">;</span> <span class="n">r</span><span class="o">++</span><span class="p">)</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">c</span> <span class="o">&lt;</span> <span class="n">cols</span><span class="p">;</span> <span class="n">c</span><span class="o">++</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">backtrack</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>In-place mutation with restore (<code class="language-plaintext highlighter-rouge">grid[r][c] = '#'</code> then restore) avoids a separate <code class="language-plaintext highlighter-rouge">visited</code> array. This is a common trick in grid backtracking.</p>

<p>Worst case: \(O(m \cdot n \cdot 4^L)\) where \(L\) is word length — but in practice pruning cuts this heavily.</p>

<hr />

<h2 id="problem-6--sudoku-solver">Problem 6 — Sudoku Solver</h2>

<p>Fill a 9×9 grid so each row, column, and 3×3 box contains digits 1–9 exactly once.</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">used_row</span><span class="p">[</span><span class="mi">9</span><span class="p">][</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{},</span> <span class="n">used_col</span><span class="p">[</span><span class="mi">9</span><span class="p">][</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{},</span> <span class="n">used_box</span><span class="p">[</span><span class="mi">9</span><span class="p">][</span><span class="mi">10</span><span class="p">]</span> <span class="o">=</span> <span class="p">{};</span>

<span class="kt">int</span> <span class="n">box</span><span class="p">(</span><span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="p">(</span><span class="n">r</span> <span class="o">/</span> <span class="mi">3</span><span class="p">)</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">c</span> <span class="o">/</span> <span class="mi">3</span><span class="p">;</span> <span class="p">}</span>

<span class="kt">bool</span> <span class="n">solve</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&gt;&amp;</span> <span class="n">board</span><span class="p">,</span> <span class="kt">int</span> <span class="n">pos</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">while</span> <span class="p">(</span><span class="n">pos</span> <span class="o">&lt;</span> <span class="mi">81</span> <span class="o">&amp;&amp;</span> <span class="n">board</span><span class="p">[</span><span class="n">pos</span><span class="o">/</span><span class="mi">9</span><span class="p">][</span><span class="n">pos</span><span class="o">%</span><span class="mi">9</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">'.'</span><span class="p">)</span> <span class="n">pos</span><span class="o">++</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">pos</span> <span class="o">==</span> <span class="mi">81</span><span class="p">)</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>

    <span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">/</span> <span class="mi">9</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">%</span> <span class="mi">9</span><span class="p">;</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">d</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">d</span> <span class="o">&lt;=</span> <span class="mi">9</span><span class="p">;</span> <span class="n">d</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">used_row</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">||</span> <span class="n">used_col</span><span class="p">[</span><span class="n">c</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">||</span> <span class="n">used_box</span><span class="p">[</span><span class="n">box</span><span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">c</span><span class="p">)][</span><span class="n">d</span><span class="p">])</span> <span class="k">continue</span><span class="p">;</span>

        <span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'0'</span> <span class="o">+</span> <span class="n">d</span><span class="p">;</span>
        <span class="n">used_row</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="n">used_col</span><span class="p">[</span><span class="n">c</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="n">used_box</span><span class="p">[</span><span class="n">box</span><span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">c</span><span class="p">)][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>

        <span class="k">if</span> <span class="p">(</span><span class="n">solve</span><span class="p">(</span><span class="n">board</span><span class="p">,</span> <span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>

        <span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="sc">'.'</span><span class="p">;</span>
        <span class="n">used_row</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="n">used_col</span><span class="p">[</span><span class="n">c</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="n">used_box</span><span class="p">[</span><span class="n">box</span><span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">c</span><span class="p">)][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">solveSudoku</span><span class="p">(</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">&gt;&gt;&amp;</span> <span class="n">board</span><span class="p">)</span> <span class="p">{</span>
    <span class="c1">// initialize constraint sets from pre-filled cells</span>
    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">r</span> <span class="o">&lt;</span> <span class="mi">9</span><span class="p">;</span> <span class="n">r</span><span class="o">++</span><span class="p">)</span>
        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">c</span> <span class="o">&lt;</span> <span class="mi">9</span><span class="p">;</span> <span class="n">c</span><span class="o">++</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">'.'</span><span class="p">)</span> <span class="p">{</span>
                <span class="kt">int</span> <span class="n">d</span> <span class="o">=</span> <span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">-</span> <span class="sc">'0'</span><span class="p">;</span>
                <span class="n">used_row</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="n">used_col</span><span class="p">[</span><span class="n">c</span><span class="p">][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="n">used_box</span><span class="p">[</span><span class="n">box</span><span class="p">(</span><span class="n">r</span><span class="p">,</span><span class="n">c</span><span class="p">)][</span><span class="n">d</span><span class="p">]</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
            <span class="p">}</span>
    <span class="n">solve</span><span class="p">(</span><span class="n">board</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Pre-computing <code class="language-plaintext highlighter-rouge">used_row/col/box</code> makes each candidate check \(O(1)\). Without this, you’d scan the row/column/box for each digit — much slower.</p>

<hr />

<h2 id="problem-7--letter-combinations-of-a-phone-number">Problem 7 — Letter Combinations of a Phone Number</h2>

<p>You’re given a sequence of digit presses on an old T9 phone keypad (digits <code class="language-plaintext highlighter-rouge">2–9</code>). Each digit maps to 2–4 letters. Return every possible string that could have been typed.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2 → abc    3 → def    4 → ghi    5 → jkl
6 → mno    7 → pqrs   8 → tuv    9 → wxyz
</code></pre></div></div>

<p>Pressing <code class="language-plaintext highlighter-rouge">2</code> then <code class="language-plaintext highlighter-rouge">3</code> can produce any of: <code class="language-plaintext highlighter-rouge">ad, ae, af, bd, be, bf, cd, ce, cf</code>.</p>

<p>This is a clean illustration of the backtracking template — the state is the combination being built, and the choices at each position are the letters mapped to that digit.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">letterCombinations</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">digits</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
        <span class="n">choices</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s">"2"</span><span class="p">:</span> <span class="s">"abc"</span><span class="p">,</span> <span class="s">"3"</span><span class="p">:</span> <span class="s">"def"</span><span class="p">,</span> <span class="s">"4"</span><span class="p">:</span> <span class="s">"ghi"</span><span class="p">,</span> <span class="s">"5"</span><span class="p">:</span> <span class="s">"jkl"</span><span class="p">,</span>
            <span class="s">"6"</span><span class="p">:</span> <span class="s">"mno"</span><span class="p">,</span> <span class="s">"7"</span><span class="p">:</span> <span class="s">"pqrs"</span><span class="p">,</span> <span class="s">"8"</span><span class="p">:</span> <span class="s">"tuv"</span><span class="p">,</span> <span class="s">"9"</span><span class="p">:</span> <span class="s">"wxyz"</span>
        <span class="p">}</span>

        <span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">digits</span><span class="p">)</span>
        <span class="n">ret</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">cur</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">pos</span> <span class="o">&gt;=</span> <span class="n">n</span><span class="p">:</span>
                <span class="n">ret</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">cur</span><span class="p">))</span>
                <span class="k">return</span>

            <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="n">choices</span><span class="p">[</span><span class="n">digits</span><span class="p">[</span><span class="n">pos</span><span class="p">]]:</span>
                <span class="n">cur</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>      <span class="c1"># choose
</span>                <span class="n">solve</span><span class="p">(</span><span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">cur</span><span class="p">)</span> <span class="c1"># explore
</span>                <span class="n">cur</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>           <span class="c1"># unchoose
</span>
        <span class="n">solve</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">[])</span>
        <span class="k">return</span> <span class="n">ret</span>
</code></pre></div></div>

<p>The decision tree has depth <code class="language-plaintext highlighter-rouge">n</code> (one level per digit) and branching factor 3 or 4 (letters per key). Total leaves = total combinations = product of letters per digit, so time is \(O(4^n \cdot n)\) in the worst case (all 9s and 7s, which map to 4 letters).</p>

<p>What makes this a good first backtracking problem: there is <strong>no pruning needed</strong> — every path from root to leaf is valid. It isolates the choose/explore/unchoose rhythm without the distraction of constraint checking.</p>

<hr />

<h2 id="problem-8--generate-parentheses">Problem 8 — Generate Parentheses</h2>

<p>Given <code class="language-plaintext highlighter-rouge">n</code> pairs of parentheses, generate every string of length <code class="language-plaintext highlighter-rouge">2n</code> that is a valid bracket sequence. For <code class="language-plaintext highlighter-rouge">n = 3</code> there are 5 such strings: <code class="language-plaintext highlighter-rouge">((()))</code>, <code class="language-plaintext highlighter-rouge">(()())</code>, <code class="language-plaintext highlighter-rouge">(())()</code>, <code class="language-plaintext highlighter-rouge">()(())</code>, <code class="language-plaintext highlighter-rouge">()()()</code>.</p>

<p>The string has <code class="language-plaintext highlighter-rouge">2n</code> positions. At each position you choose <code class="language-plaintext highlighter-rouge">(</code> or <code class="language-plaintext highlighter-rouge">)</code>. The trick is knowing when <code class="language-plaintext highlighter-rouge">)</code> is legal — you need to track how many unmatched opens you have so far (<code class="language-plaintext highlighter-rouge">cur</code>):</p>

<ul>
  <li>You can always add <code class="language-plaintext highlighter-rouge">(</code>, which increments <code class="language-plaintext highlighter-rouge">cur</code>.</li>
  <li>You can only add <code class="language-plaintext highlighter-rouge">)</code> when <code class="language-plaintext highlighter-rouge">cur &gt; 0</code> (there’s an open bracket to close).</li>
  <li>At position <code class="language-plaintext highlighter-rouge">2n</code>, the string is valid iff <code class="language-plaintext highlighter-rouge">cur == 0</code> (all brackets matched).</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Solution</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">generateParenthesis</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
        <span class="n">ret</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">def</span> <span class="nf">solve</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">res</span><span class="p">,</span> <span class="n">cur</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">pos</span> <span class="o">&gt;=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">n</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">cur</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>          <span class="c1"># all brackets matched
</span>                    <span class="n">ret</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">res</span><span class="p">))</span>
                <span class="k">return</span>

            <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="s">'()'</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">ch</span> <span class="o">==</span> <span class="s">'('</span><span class="p">:</span>
                    <span class="n">res</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>
                    <span class="n">solve</span><span class="p">(</span><span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">res</span><span class="p">,</span> <span class="n">cur</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>  <span class="c1"># one more unmatched open
</span>                    <span class="n">res</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
                <span class="k">elif</span> <span class="n">ch</span> <span class="o">==</span> <span class="s">')'</span> <span class="ow">and</span> <span class="n">cur</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>       <span class="c1"># prune: can't close what isn't open
</span>                    <span class="n">res</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>
                    <span class="n">solve</span><span class="p">(</span><span class="n">pos</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">res</span><span class="p">,</span> <span class="n">cur</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
                    <span class="n">res</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>

        <span class="n">solve</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">[],</span> <span class="mi">0</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">ret</span>
</code></pre></div></div>

<p>The pruning <code class="language-plaintext highlighter-rouge">cur &gt; 0</code> is what prevents invalid sequences — it cuts every branch that would produce a <code class="language-plaintext highlighter-rouge">)</code> with nothing to close. This eliminates the need to validate at the leaf.</p>

<p>Compare this to Letter Combinations (Problem 7): there, every path was valid and we only checked at the leaf. Here, the constraint (<code class="language-plaintext highlighter-rouge">cur &gt; 0</code>) is checked <strong>mid-path</strong>, halving the branches at each <code class="language-plaintext highlighter-rouge">)</code> decision.</p>

<p>Time complexity: \(O(4^n / \sqrt{n})\) — the number of valid sequences is the \(n\)-th Catalan number \(C_n = \frac{1}{n+1}\binom{2n}{n}\), which grows as \(O(4^n / n^{3/2})\). Each sequence takes \(O(n)\) to copy, giving the total.</p>

<hr />

<h2 id="recognizing-when-to-prune">Recognizing when to prune</h2>

<p>Backtracking without pruning is just brute force. The speedup comes entirely from cutting branches early. Ask:</p>

<ul>
  <li><strong>Can this partial state ever reach a valid solution?</strong> If not, return immediately.</li>
  <li><strong>Is the current cost/sum already beyond the target?</strong> Break (especially if candidates are sorted).</li>
  <li><strong>Is a constraint already violated?</strong> Skip before recursing.</li>
</ul>

<hr />

<h2 id="patterns-summary">Patterns summary</h2>

<table>
  <thead>
    <tr>
      <th>Problem</th>
      <th>Choice at each step</th>
      <th>Key pruning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Subsets</td>
      <td>include or skip <code class="language-plaintext highlighter-rouge">a[i]</code></td>
      <td>iterate <code class="language-plaintext highlighter-rouge">j</code> from <code class="language-plaintext highlighter-rouge">i</code> forward</td>
    </tr>
    <tr>
      <td>Permutations</td>
      <td>place which element at <code class="language-plaintext highlighter-rouge">start</code></td>
      <td>skip duplicates at same depth</td>
    </tr>
    <tr>
      <td>Combination Sum</td>
      <td>pick <code class="language-plaintext highlighter-rouge">a[i]</code> (reusable) or move on</td>
      <td><code class="language-plaintext highlighter-rouge">a[i] &gt; remaining</code> → break</td>
    </tr>
    <tr>
      <td>N-Queens</td>
      <td>place queen in which column for this row</td>
      <td>bitmask/boolean for col, diag</td>
    </tr>
    <tr>
      <td>Word Search</td>
      <td>extend path in 4 directions</td>
      <td>cell mismatch or already visited</td>
    </tr>
    <tr>
      <td>Sudoku</td>
      <td>which digit fills this cell</td>
      <td>row/col/box constraint sets</td>
    </tr>
    <tr>
      <td>Letter Combinations</td>
      <td>which letter maps to this digit</td>
      <td>none — all paths are valid</td>
    </tr>
    <tr>
      <td>Generate Parentheses</td>
      <td>add <code class="language-plaintext highlighter-rouge">(</code> or <code class="language-plaintext highlighter-rouge">)</code> at each position</td>
      <td><code class="language-plaintext highlighter-rouge">)</code> only when <code class="language-plaintext highlighter-rouge">cur &gt; 0</code></td>
    </tr>
  </tbody>
</table>

<p><strong>The mental checklist:</strong></p>
<ol>
  <li>What is the partial state?</li>
  <li>What are the choices at each step?</li>
  <li>What makes a choice invalid (prune)?</li>
  <li>What makes the state complete (record)?</li>
  <li>Does undo fully restore the state?</li>
</ol>]]></content><author><name>Seroze</name></author><category term="competitive-programming" /><category term="competitive-programming" /><category term="backtracking" /><category term="recursion" /><category term="dfs" /><summary type="html"><![CDATA[Backtracking is just DFS on a decision tree — at each node you make a choice, recurse into it, and undo the choice before trying the next one.]]></summary></entry><entry><title type="html">Gradle Basics — Init, Build, Test, and the Wrapper</title><link href="/gradle-basics/" rel="alternate" type="text/html" title="Gradle Basics — Init, Build, Test, and the Wrapper" /><published>2026-06-18T18:30:00+00:00</published><updated>2026-06-18T18:30:00+00:00</updated><id>/gradle-basics</id><content type="html" xml:base="/gradle-basics/"><![CDATA[<p><em>Gradle is a build tool — it compiles your code, resolves dependencies, runs tests, and packages your application. This post covers the day-to-day commands and the concepts behind them.</em></p>

<hr />

<h2 id="creating-a-project-with-gradle-init">Creating a project with <code class="language-plaintext highlighter-rouge">gradle init</code></h2>

<p><code class="language-plaintext highlighter-rouge">gradle init</code> is an interactive wizard that scaffolds a new project. Run it in an empty directory:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">mkdir </span>my-app <span class="o">&amp;&amp;</span> <span class="nb">cd </span>my-app
gradle init
</code></pre></div></div>

<p>It will ask:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Select type of project to generate:
  1: basic
  2: application       ← pick this for a runnable app
  3: library
  4: Gradle plugin

Select implementation language:
  1: Java

Select build script DSL:
  1: Kotlin             ← build.gradle.kts
  2: Groovy             ← build.gradle

Project name: my-app
Source package: com.example
</code></pre></div></div>

<p>After finishing, you get:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>my-app/
├── gradlew                        # Gradle wrapper script (Linux/Mac)
├── gradlew.bat                    # Gradle wrapper script (Windows)
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar     # wrapper bootstrap binary
│       └── gradle-wrapper.properties  # which Gradle version to use
├── settings.gradle.kts            # project name, subproject list
├── build.gradle.kts               # dependencies, plugins, build config
└── src/
    ├── main/java/com/example/
    │   └── App.java
    └── test/java/com/example/
        └── AppTest.java
</code></pre></div></div>

<p><strong>The source directory convention</strong></p>

<p>Gradle follows the Maven standard layout. The package name becomes a nested directory path under <code class="language-plaintext highlighter-rouge">src/main/java/</code> and <code class="language-plaintext highlighter-rouge">src/test/java/</code>. For a package <code class="language-plaintext highlighter-rouge">com.ridesharing</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>src/
├── main/
│   └── java/
│       └── com/
│           └── ridesharing/
│               ├── Main.java
│               ├── Driver.java
│               └── Trip.java
└── test/
    └── java/
        └── com/
            └── ridesharing/
                ├── MainTest.java
                ├── DriverTest.java
                └── TripTest.java
</code></pre></div></div>

<p>The test package mirrors the main package exactly. This is convention, not enforced — but it means test classes get package-private access to the classes they test without needing everything to be <code class="language-plaintext highlighter-rouge">public</code>.</p>

<p>When Gradle compiles, <code class="language-plaintext highlighter-rouge">src/main/java</code> goes to <code class="language-plaintext highlighter-rouge">build/classes/java/main/</code> and <code class="language-plaintext highlighter-rouge">src/test/java</code> goes to <code class="language-plaintext highlighter-rouge">build/classes/java/test/</code>. The test classpath includes both so tests can import production classes.</p>

<hr />

<h2 id="the-build-file">The build file</h2>

<p><code class="language-plaintext highlighter-rouge">build.gradle.kts</code> (Kotlin DSL) for a Java application looks like this:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">plugins</span> <span class="p">{</span>
    <span class="n">java</span>                         <span class="c1">// compiles Java source</span>
    <span class="n">application</span>                  <span class="c1">// adds 'run' task and creates a distribution</span>
<span class="p">}</span>

<span class="nf">repositories</span> <span class="p">{</span>
    <span class="nf">mavenCentral</span><span class="p">()</span>               <span class="c1">// where to download dependencies from</span>
<span class="p">}</span>

<span class="nf">dependencies</span> <span class="p">{</span>
    <span class="nf">testImplementation</span><span class="p">(</span><span class="s">"org.junit.jupiter:junit-jupiter:5.10.0"</span><span class="p">)</span>
<span class="p">}</span>

<span class="nf">application</span> <span class="p">{</span>
    <span class="n">mainClass</span> <span class="p">=</span> <span class="s">"com.example.App"</span>  <span class="c1">// entry point for ./gradlew run</span>
<span class="p">}</span>

<span class="n">tasks</span><span class="p">.</span><span class="nf">test</span> <span class="p">{</span>
    <span class="nf">useJUnitPlatform</span><span class="p">()</span>           <span class="c1">// tell Gradle to use JUnit 5 runner</span>
<span class="p">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">settings.gradle.kts</code> just names the project and lists subprojects (for single-project builds, it’s minimal):</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rootProject</span><span class="p">.</span><span class="n">name</span> <span class="p">=</span> <span class="s">"my-app"</span>
</code></pre></div></div>

<hr />

<h2 id="key-commands">Key commands</h2>

<p>All commands use <code class="language-plaintext highlighter-rouge">./gradlew</code> (the wrapper) rather than <code class="language-plaintext highlighter-rouge">gradle</code> directly — more on why below.</p>

<h3 id="gradlew-tasks"><code class="language-plaintext highlighter-rouge">./gradlew tasks</code></h3>

<p>Lists every available task and a short description. Good starting point when you’re unfamiliar with a project.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew tasks
</code></pre></div></div>

<h3 id="gradlew-build"><code class="language-plaintext highlighter-rouge">./gradlew build</code></h3>

<p>The main command. It:</p>
<ol>
  <li>Compiles <code class="language-plaintext highlighter-rouge">src/main/java</code> → <code class="language-plaintext highlighter-rouge">build/classes/java/main/</code></li>
  <li>Compiles <code class="language-plaintext highlighter-rouge">src/test/java</code> → <code class="language-plaintext highlighter-rouge">build/classes/java/test/</code></li>
  <li>Runs all tests</li>
  <li>Packages everything into a JAR at <code class="language-plaintext highlighter-rouge">build/libs/my-app.jar</code></li>
</ol>

<p>If any test fails, the build fails.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew build
</code></pre></div></div>

<h3 id="gradlew-run"><code class="language-plaintext highlighter-rouge">./gradlew run</code></h3>

<p>Compiles (if needed) and runs the class specified in <code class="language-plaintext highlighter-rouge">application.mainClass</code>.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew run
</code></pre></div></div>

<p>Pass arguments via <code class="language-plaintext highlighter-rouge">--args</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew run <span class="nt">--args</span><span class="o">=</span><span class="s2">"hello world"</span>
</code></pre></div></div>

<h3 id="gradlew-test"><code class="language-plaintext highlighter-rouge">./gradlew test</code></h3>

<p>Compiles and runs tests only. After it finishes, a human-readable HTML report is generated at:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>build/reports/tests/test/index.html
</code></pre></div></div>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew <span class="nb">test</span>

<span class="c"># Run a specific test class</span>
./gradlew <span class="nb">test</span> <span class="nt">--tests</span> <span class="s2">"com.example.AppTest"</span>

<span class="c"># Run a specific test method</span>
./gradlew <span class="nb">test</span> <span class="nt">--tests</span> <span class="s2">"com.example.AppTest.shouldReturnTrue"</span>
</code></pre></div></div>

<h3 id="gradlew-clean"><code class="language-plaintext highlighter-rouge">./gradlew clean</code></h3>

<p>Deletes the <code class="language-plaintext highlighter-rouge">build/</code> directory. Use this when you want a completely fresh build — useful when you suspect stale compiled classes are causing weird behavior.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew clean build   <span class="c"># clean then build in one shot</span>
</code></pre></div></div>

<h3 id="gradlew-jar"><code class="language-plaintext highlighter-rouge">./gradlew jar</code></h3>

<p>Builds just the JAR without running tests.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew jar
<span class="c"># output: build/libs/my-app.jar</span>
</code></pre></div></div>

<hr />

<h2 id="what-happens-during-a-build--the-three-phases">What happens during a build — the three phases</h2>

<p>Gradle processes every build in exactly three phases, in order:</p>

<p><strong>1. Initialization</strong> — Gradle reads <code class="language-plaintext highlighter-rouge">settings.gradle.kts</code> to find which projects exist and sets up the project hierarchy.</p>

<p><strong>2. Configuration</strong> — Gradle evaluates every <code class="language-plaintext highlighter-rouge">build.gradle.kts</code> file. This does NOT run tasks yet — it just builds a graph of all tasks and their dependencies. This is why you can print <code class="language-plaintext highlighter-rouge">tasks</code> without actually compiling anything.</p>

<p><strong>3. Execution</strong> — Gradle looks at which tasks you asked for, resolves the dependency graph (e.g., <code class="language-plaintext highlighter-rouge">test</code> depends on <code class="language-plaintext highlighter-rouge">compileTestJava</code> which depends on <code class="language-plaintext highlighter-rouge">compileJava</code>), and executes them in the correct order.</p>

<p>This separation is important: code at the top level of <code class="language-plaintext highlighter-rouge">build.gradle.kts</code> runs at configuration time (phase 2), not at execution time. Mistakes here cause slow configuration or broken task graphs.</p>

<hr />

<h2 id="incremental-builds-and-the-build-cache">Incremental builds and the build cache</h2>

<p>Gradle tracks the inputs and outputs of every task. If nothing changed since the last run, it skips the task and prints <code class="language-plaintext highlighter-rouge">UP-TO-DATE</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; Task :compileJava UP-TO-DATE
&gt; Task :processResources UP-TO-DATE
&gt; Task :classes UP-TO-DATE
&gt; Task :test UP-TO-DATE
</code></pre></div></div>

<p>This makes repeated builds very fast. <code class="language-plaintext highlighter-rouge">./gradlew clean</code> throws this away — only do it when something is genuinely wrong, not as a habit.</p>

<hr />

<h2 id="dependencies--implementation-vs-api-vs-testimplementation">Dependencies — <code class="language-plaintext highlighter-rouge">implementation</code> vs <code class="language-plaintext highlighter-rouge">api</code> vs <code class="language-plaintext highlighter-rouge">testImplementation</code></h2>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">dependencies</span> <span class="p">{</span>
    <span class="nf">implementation</span><span class="p">(</span><span class="s">"com.google.guava:guava:32.0.0"</span><span class="p">)</span>
        <span class="c1">// available in your main code, NOT exposed to callers of your library</span>

    <span class="nf">api</span><span class="p">(</span><span class="s">"com.fasterxml.jackson.core:jackson-databind:2.15.0"</span><span class="p">)</span>
        <span class="c1">// available in main code AND exposed to callers (for libraries only)</span>

    <span class="nf">testImplementation</span><span class="p">(</span><span class="s">"org.junit.jupiter:junit-jupiter:5.10.0"</span><span class="p">)</span>
        <span class="c1">// available only in test source set</span>

    <span class="nf">runtimeOnly</span><span class="p">(</span><span class="s">"org.slf4j:slf4j-simple:2.0.0"</span><span class="p">)</span>
        <span class="c1">// only on classpath at runtime, not at compile time</span>
<span class="p">}</span>
</code></pre></div></div>

<p>For application projects (not libraries), use <code class="language-plaintext highlighter-rouge">implementation</code> for everything — <code class="language-plaintext highlighter-rouge">api</code> only matters when other projects depend on your project as a library.</p>

<hr />

<h2 id="the-gradle-wrapper--gradlew-vs-gradle">The Gradle Wrapper — <code class="language-plaintext highlighter-rouge">gradlew</code> vs <code class="language-plaintext highlighter-rouge">gradle</code></h2>

<p>The wrapper is the recommended way to run Gradle. Instead of using a globally installed <code class="language-plaintext highlighter-rouge">gradle</code> command, you use <code class="language-plaintext highlighter-rouge">./gradlew</code> — a small script that downloads and caches the exact Gradle version specified in <code class="language-plaintext highlighter-rouge">gradle/wrapper/gradle-wrapper.properties</code>.</p>

<div class="language-properties highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># gradle/wrapper/gradle-wrapper.properties
</span><span class="py">distributionUrl</span><span class="p">=</span><span class="s">https</span><span class="se">\:</span><span class="s">//services.gradle.org/distributions/gradle-8.7-bin.zip</span>
</code></pre></div></div>

<p><strong>Why use the wrapper instead of global Gradle?</strong></p>

<p><strong>Reproducibility</strong> — everyone on the team uses the exact same Gradle version. “Works on my machine” build failures caused by version mismatches disappear.</p>

<p><strong>No installation required</strong> — a new team member clones the repo and runs <code class="language-plaintext highlighter-rouge">./gradlew build</code>. They don’t need to install anything. The wrapper downloads the right Gradle version automatically on first run.</p>

<p><strong>CI/CD friendly</strong> — your CI pipeline just runs <code class="language-plaintext highlighter-rouge">./gradlew build</code>. No setup step to install a specific Gradle version. No drift between what CI uses and what developers use.</p>

<p><strong>Upgrading is explicit and tracked</strong> — to upgrade Gradle, run:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew wrapper <span class="nt">--gradle-version</span> 8.8
</code></pre></div></div>
<p>This updates <code class="language-plaintext highlighter-rouge">gradle-wrapper.properties</code>, which you commit to version control. Every developer and CI job gets the upgrade automatically on next pull. There’s a clear history of when and why the version changed.</p>

<p><strong>Commit the wrapper, not the distribution</strong> — commit <code class="language-plaintext highlighter-rouge">gradlew</code>, <code class="language-plaintext highlighter-rouge">gradlew.bat</code>, <code class="language-plaintext highlighter-rouge">gradle/wrapper/gradle-wrapper.jar</code>, and <code class="language-plaintext highlighter-rouge">gradle/wrapper/gradle-wrapper.properties</code>. Do not commit the downloaded Gradle distribution itself (it lives in <code class="language-plaintext highlighter-rouge">~/.gradle/wrapper/dists/</code>).</p>

<hr />

<h2 id="multi-project-builds">Multi-project builds</h2>

<p>Large projects split into subprojects (modules). The root <code class="language-plaintext highlighter-rouge">settings.gradle.kts</code> declares them:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rootProject</span><span class="p">.</span><span class="n">name</span> <span class="p">=</span> <span class="s">"my-app"</span>
<span class="nf">include</span><span class="p">(</span><span class="s">"core"</span><span class="p">,</span> <span class="s">"api"</span><span class="p">,</span> <span class="s">"web"</span><span class="p">)</span>
</code></pre></div></div>

<p>Each subproject has its own <code class="language-plaintext highlighter-rouge">build.gradle.kts</code>. A subproject can depend on another:</p>

<div class="language-kotlin highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// web/build.gradle.kts</span>
<span class="nf">dependencies</span> <span class="p">{</span>
    <span class="nf">implementation</span><span class="p">(</span><span class="nf">project</span><span class="p">(</span><span class="s">":core"</span><span class="p">))</span>
    <span class="nf">implementation</span><span class="p">(</span><span class="nf">project</span><span class="p">(</span><span class="s">":api"</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Build a specific subproject:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>./gradlew :web:build
./gradlew :core:test
</code></pre></div></div>

<hr />

<h2 id="quick-reference">Quick reference</h2>

<table>
  <thead>
    <tr>
      <th>Command</th>
      <th>What it does</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew tasks</code></td>
      <td>List all available tasks</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew build</code></td>
      <td>Compile + test + package JAR</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew run</code></td>
      <td>Compile and run the main class</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew test</code></td>
      <td>Compile and run tests only</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew clean</code></td>
      <td>Delete build/ directory</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew jar</code></td>
      <td>Package JAR without running tests</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew dependencies</code></td>
      <td>Show dependency tree</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew wrapper --gradle-version X</code></td>
      <td>Upgrade the wrapper to version X</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">./gradlew build --scan</code></td>
      <td>Upload build scan to scans.gradle.com for debugging</td>
    </tr>
  </tbody>
</table>

<p><strong>The rule on <code class="language-plaintext highlighter-rouge">gradlew</code> vs <code class="language-plaintext highlighter-rouge">gradle</code>:</strong> always use <code class="language-plaintext highlighter-rouge">./gradlew</code>. Never rely on a globally installed <code class="language-plaintext highlighter-rouge">gradle</code> for project builds — it defeats the purpose of the wrapper.</p>]]></content><author><name>Seroze</name></author><category term="java" /><category term="java" /><category term="gradle" /><category term="build-tools" /><summary type="html"><![CDATA[Gradle is a build tool — it compiles your code, resolves dependencies, runs tests, and packages your application. This post covers the day-to-day commands and the concepts behind them.]]></summary></entry><entry><title type="html">Comparator Interface in Java</title><link href="/java-comparator/" rel="alternate" type="text/html" title="Comparator Interface in Java" /><published>2026-06-18T18:30:00+00:00</published><updated>2026-06-18T18:30:00+00:00</updated><id>/java-comparator</id><content type="html" xml:base="/java-comparator/"><![CDATA[<p><em>Comparator is one of those interfaces you’ll use in almost every Java project. Getting fluent with it saves a lot of cognitive overhead.</em></p>

<hr />

<h2 id="comparable-vs-comparator">Comparable vs Comparator</h2>

<p>Java has two ways to define ordering:</p>

<p><strong><code class="language-plaintext highlighter-rouge">Comparable&lt;T&gt;</code></strong> — the object defines its own natural ordering by implementing <code class="language-plaintext highlighter-rouge">compareTo</code>. One ordering per class, baked in.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">Student</span> <span class="kd">implements</span> <span class="nc">Comparable</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="o">{</span>
    <span class="nc">String</span> <span class="n">name</span><span class="o">;</span>
    <span class="kt">int</span> <span class="n">age</span><span class="o">;</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="kt">int</span> <span class="nf">compareTo</span><span class="o">(</span><span class="nc">Student</span> <span class="n">other</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">return</span> <span class="nc">Integer</span><span class="o">.</span><span class="na">compare</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">age</span><span class="o">,</span> <span class="n">other</span><span class="o">.</span><span class="na">age</span><span class="o">);</span> <span class="c1">// natural order: by age</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">Collections</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">list</span><span class="o">);</span> <span class="c1">// uses compareTo</span>
</code></pre></div></div>

<p><strong><code class="language-plaintext highlighter-rouge">Comparator&lt;T&gt;</code></strong> — an external object defines an ordering. You can have as many as you want, and you don’t need to touch the class.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">byName</span> <span class="o">=</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">a</span><span class="o">.</span><span class="na">name</span><span class="o">.</span><span class="na">compareTo</span><span class="o">(</span><span class="n">b</span><span class="o">.</span><span class="na">name</span><span class="o">);</span>
<span class="n">list</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">byName</span><span class="o">);</span>
</code></pre></div></div>

<p>Use <code class="language-plaintext highlighter-rouge">Comparable</code> for the one obvious natural ordering (e.g., integers by value, strings lexicographically). Use <code class="language-plaintext highlighter-rouge">Comparator</code> for everything else — alternate orderings, anonymous sorts, and when you don’t own the class.</p>

<hr />

<h2 id="the-compare-contract">The <code class="language-plaintext highlighter-rouge">compare</code> contract</h2>

<p><code class="language-plaintext highlighter-rouge">compare(a, b)</code> must return:</p>
<ul>
  <li><strong>negative</strong> — <code class="language-plaintext highlighter-rouge">a</code> should come before <code class="language-plaintext highlighter-rouge">b</code></li>
  <li><strong>zero</strong> — <code class="language-plaintext highlighter-rouge">a</code> and <code class="language-plaintext highlighter-rouge">b</code> are equal in ordering</li>
  <li><strong>positive</strong> — <code class="language-plaintext highlighter-rouge">b</code> should come before <code class="language-plaintext highlighter-rouge">a</code></li>
</ul>

<p>The one rule to remember: <strong>the first argument to <code class="language-plaintext highlighter-rouge">Integer.compare(x, y)</code> is what you want out first.</strong></p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// ascending: small values first</span>
<span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">Integer</span><span class="o">.</span><span class="na">compare</span><span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span>

<span class="c1">// descending: large values first</span>
<span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="nc">Integer</span><span class="o">.</span><span class="na">compare</span><span class="o">(</span><span class="n">b</span><span class="o">,</span> <span class="n">a</span><span class="o">)</span>
</code></pre></div></div>

<p>Avoid <code class="language-plaintext highlighter-rouge">a - b</code> subtraction — it overflows when values are large or negative. Always use <code class="language-plaintext highlighter-rouge">Integer.compare</code> or <code class="language-plaintext highlighter-rouge">Double.compare</code>.</p>

<hr />

<h2 id="comparator-factory-methods">Comparator factory methods</h2>

<p>Since Java 8, <code class="language-plaintext highlighter-rouge">Comparator</code> has static factory methods that let you build comparators without writing the comparison logic manually.</p>

<h3 id="comparatorcomparing"><code class="language-plaintext highlighter-rouge">Comparator.comparing</code></h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Sort students by name</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">byName</span> <span class="o">=</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparing</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">name</span><span class="o">);</span>

<span class="c1">// With method reference (cleaner)</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">byName</span> <span class="o">=</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">);</span>
</code></pre></div></div>

<h3 id="comparingint-comparingdouble-comparinglong"><code class="language-plaintext highlighter-rouge">comparingInt</code>, <code class="language-plaintext highlighter-rouge">comparingDouble</code>, <code class="language-plaintext highlighter-rouge">comparingLong</code></h3>

<p>Prefer these over <code class="language-plaintext highlighter-rouge">comparing</code> when the key is a primitive — they avoid boxing.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">byAge</span> <span class="o">=</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">);</span>
</code></pre></div></div>

<hr />

<h2 id="chaining-with-thencomparing">Chaining with <code class="language-plaintext highlighter-rouge">thenComparing</code></h2>

<p>Sort by a primary key, break ties with a secondary key.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Sort by age ascending, then by name ascending for same age</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span>
    <span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">)</span>
    <span class="o">.</span><span class="na">thenComparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">);</span>

<span class="n">list</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">cmp</span><span class="o">);</span>
</code></pre></div></div>

<p>You can chain as many levels as needed:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Employee</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span>
    <span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Employee:</span><span class="o">:</span><span class="n">getDepartment</span><span class="o">)</span>
    <span class="o">.</span><span class="na">thenComparingInt</span><span class="o">(</span><span class="nl">Employee:</span><span class="o">:</span><span class="n">getSalary</span><span class="o">)</span>
    <span class="o">.</span><span class="na">thenComparing</span><span class="o">(</span><span class="nl">Employee:</span><span class="o">:</span><span class="n">getName</span><span class="o">);</span>
</code></pre></div></div>

<hr />

<h2 id="reversing-order-with-reversed">Reversing order with <code class="language-plaintext highlighter-rouge">reversed()</code></h2>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Descending by age</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">byAgeDesc</span> <span class="o">=</span> <span class="nc">Comparator</span>
    <span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">)</span>
    <span class="o">.</span><span class="na">reversed</span><span class="o">();</span>

<span class="c1">// Descending primary, ascending secondary</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span>
    <span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">).</span><span class="na">reversed</span><span class="o">()</span>
    <span class="o">.</span><span class="na">thenComparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">);</span>       <span class="c1">// name still ascending</span>
</code></pre></div></div>

<p>Be careful about where you call <code class="language-plaintext highlighter-rouge">reversed()</code> — it reverses everything chained before it, not just the last key.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Reverses BOTH keys</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span>
    <span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">)</span>
    <span class="o">.</span><span class="na">thenComparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">)</span>
    <span class="o">.</span><span class="na">reversed</span><span class="o">();</span>

<span class="c1">// Reverses ONLY age, name stays ascending</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span>
    <span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">).</span><span class="na">reversed</span><span class="o">()</span>
    <span class="o">.</span><span class="na">thenComparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">);</span>
</code></pre></div></div>

<p>For mixed directions (ascending primary, descending secondary) without <code class="language-plaintext highlighter-rouge">reversed()</code>, write the secondary comparator manually:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span>
    <span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">)</span>                              <span class="c1">// age ascending</span>
    <span class="o">.</span><span class="na">thenComparing</span><span class="o">((</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">b</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">compareTo</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">getName</span><span class="o">()));</span> <span class="c1">// name descending</span>
</code></pre></div></div>

<hr />

<h2 id="handling-nulls">Handling nulls</h2>

<p><code class="language-plaintext highlighter-rouge">Comparator.nullsFirst</code> and <code class="language-plaintext highlighter-rouge">Comparator.nullsLast</code> wrap another comparator and push null values to the front or back.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Nulls sort to the front, non-nulls sort by name</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">nullsFirst</span><span class="o">(</span>
    <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">)</span>
<span class="o">);</span>

<span class="c1">// Nulls sort to the back</span>
<span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">cmp</span> <span class="o">=</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">nullsLast</span><span class="o">(</span>
    <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">)</span>
<span class="o">);</span>
</code></pre></div></div>

<hr />

<h2 id="where-comparator-is-used">Where Comparator is used</h2>

<p><strong><code class="language-plaintext highlighter-rouge">List.sort</code> and <code class="language-plaintext highlighter-rouge">Collections.sort</code>:</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">list</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">));</span>
<span class="nc">Collections</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">list</span><span class="o">,</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">));</span>
</code></pre></div></div>

<p><strong><code class="language-plaintext highlighter-rouge">Arrays.sort</code></strong> (object arrays only — <code class="language-plaintext highlighter-rouge">int[]</code> doesn’t accept a comparator):</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Student</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="o">...;</span>
<span class="nc">Arrays</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">arr</span><span class="o">,</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">));</span>
</code></pre></div></div>

<p><strong><code class="language-plaintext highlighter-rouge">PriorityQueue</code></strong> constructor:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Min by age</span>
<span class="nc">PriorityQueue</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">pq</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PriorityQueue</span><span class="o">&lt;&gt;(</span>
    <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">)</span>
<span class="o">);</span>

<span class="c1">// Max by age</span>
<span class="nc">PriorityQueue</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">pq</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PriorityQueue</span><span class="o">&lt;&gt;(</span>
    <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">).</span><span class="na">reversed</span><span class="o">()</span>
<span class="o">);</span>
</code></pre></div></div>

<p><strong><code class="language-plaintext highlighter-rouge">TreeMap</code> and <code class="language-plaintext highlighter-rouge">TreeSet</code></strong> constructor:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// TreeSet ordered by name</span>
<span class="nc">TreeSet</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">ts</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TreeSet</span><span class="o">&lt;&gt;(</span><span class="nc">Comparator</span><span class="o">.</span><span class="na">comparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">));</span>

<span class="c1">// TreeMap ordered by key length</span>
<span class="nc">TreeMap</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">tm</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TreeMap</span><span class="o">&lt;&gt;(</span>
    <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">String:</span><span class="o">:</span><span class="n">length</span><span class="o">).</span><span class="na">thenComparing</span><span class="o">(</span><span class="nc">Comparator</span><span class="o">.</span><span class="na">naturalOrder</span><span class="o">())</span>
<span class="o">);</span>
</code></pre></div></div>

<hr />

<h2 id="storing-and-reusing-comparators">Storing and reusing comparators</h2>

<p>Comparators are objects — you can store them in variables, pass them around, and compose them.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">StudentComparators</span> <span class="o">{</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="no">BY_AGE</span> <span class="o">=</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">);</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="no">BY_NAME</span> <span class="o">=</span> <span class="nc">Comparator</span><span class="o">.</span><span class="na">comparing</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">);</span>
    <span class="kd">static</span> <span class="kd">final</span> <span class="nc">Comparator</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="no">BY_AGE_THEN_NAME</span> <span class="o">=</span> <span class="no">BY_AGE</span><span class="o">.</span><span class="na">thenComparing</span><span class="o">(</span><span class="no">BY_NAME</span><span class="o">);</span>
<span class="o">}</span>

<span class="n">list</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="nc">StudentComparators</span><span class="o">.</span><span class="na">BY_AGE_THEN_NAME</span><span class="o">);</span>
<span class="n">pq</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PriorityQueue</span><span class="o">&lt;&gt;(</span><span class="nc">StudentComparators</span><span class="o">.</span><span class="na">BY_AGE</span><span class="o">);</span>
</code></pre></div></div>

<hr />

<h2 id="quick-reference">Quick reference</h2>

<table>
  <thead>
    <tr>
      <th>Goal</th>
      <th>Code</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sort ascending by int field</td>
      <td><code class="language-plaintext highlighter-rouge">Comparator.comparingInt(T::getField)</code></td>
    </tr>
    <tr>
      <td>Sort descending</td>
      <td><code class="language-plaintext highlighter-rouge">.reversed()</code></td>
    </tr>
    <tr>
      <td>Break ties</td>
      <td><code class="language-plaintext highlighter-rouge">.thenComparing(...)</code> or <code class="language-plaintext highlighter-rouge">.thenComparingInt(...)</code></td>
    </tr>
    <tr>
      <td>Null-safe</td>
      <td><code class="language-plaintext highlighter-rouge">Comparator.nullsFirst(inner)</code> / <code class="language-plaintext highlighter-rouge">nullsLast(inner)</code></td>
    </tr>
    <tr>
      <td>Natural order</td>
      <td><code class="language-plaintext highlighter-rouge">Comparator.naturalOrder()</code></td>
    </tr>
    <tr>
      <td>Reverse natural order</td>
      <td><code class="language-plaintext highlighter-rouge">Comparator.reverseOrder()</code></td>
    </tr>
    <tr>
      <td>Custom two-field compare</td>
      <td><code class="language-plaintext highlighter-rouge">(a, b) -&gt; Integer.compare(a.x, b.x)</code></td>
    </tr>
  </tbody>
</table>

<p><strong>The one rule:</strong> <code class="language-plaintext highlighter-rouge">Integer.compare(X, Y)</code> means X comes before Y. Put the value you want out first as the first argument.</p>]]></content><author><name>Seroze</name></author><category term="java" /><category term="java" /><category term="comparator" /><category term="sorting" /><summary type="html"><![CDATA[Comparator is one of those interfaces you’ll use in almost every Java project. Getting fluent with it saves a lot of cognitive overhead.]]></summary></entry><entry><title type="html">Streams in Java</title><link href="/java-streams/" rel="alternate" type="text/html" title="Streams in Java" /><published>2026-06-18T18:30:00+00:00</published><updated>2026-06-18T18:30:00+00:00</updated><id>/java-streams</id><content type="html" xml:base="/java-streams/"><![CDATA[<p><em>A Stream is not a data structure — it’s a pipeline. You describe what you want, and the stream figures out how to compute it lazily.</em></p>

<hr />

<h2 id="what-is-a-stream">What is a Stream?</h2>

<p>A <code class="language-plaintext highlighter-rouge">Stream&lt;T&gt;</code> is a sequence of elements that supports a pipeline of operations. The key properties:</p>

<ul>
  <li><strong>Not a data structure</strong> — it doesn’t store elements. It pulls them from a source (collection, array, generator).</li>
  <li><strong>Lazy</strong> — intermediate operations are not executed until a terminal operation is called.</li>
  <li><strong>Single-use</strong> — once consumed, a stream cannot be reused.</li>
</ul>

<p>A pipeline has three parts:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>source → intermediate operations (lazy) → terminal operation (triggers execution)
</code></pre></div></div>

<hr />

<h2 id="creating-streams">Creating streams</h2>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// From a collection</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">names</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"Alice"</span><span class="o">,</span> <span class="s">"Bob"</span><span class="o">,</span> <span class="s">"Charlie"</span><span class="o">);</span>
<span class="nc">Stream</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">s</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">();</span>

<span class="c1">// From an array</span>
<span class="kt">int</span><span class="o">[]</span> <span class="n">arr</span> <span class="o">=</span> <span class="o">{</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">};</span>
<span class="nc">IntStream</span> <span class="n">s</span> <span class="o">=</span> <span class="nc">Arrays</span><span class="o">.</span><span class="na">stream</span><span class="o">(</span><span class="n">arr</span><span class="o">);</span>

<span class="c1">// From values directly</span>
<span class="nc">Stream</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">s</span> <span class="o">=</span> <span class="nc">Stream</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"a"</span><span class="o">,</span> <span class="s">"b"</span><span class="o">,</span> <span class="s">"c"</span><span class="o">);</span>

<span class="c1">// Infinite stream — generate</span>
<span class="nc">Stream</span><span class="o">&lt;</span><span class="nc">Double</span><span class="o">&gt;</span> <span class="n">randoms</span> <span class="o">=</span> <span class="nc">Stream</span><span class="o">.</span><span class="na">generate</span><span class="o">(</span><span class="nl">Math:</span><span class="o">:</span><span class="n">random</span><span class="o">);</span>

<span class="c1">// Infinite stream — iterate (like a for loop)</span>
<span class="nc">Stream</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">naturals</span> <span class="o">=</span> <span class="nc">Stream</span><span class="o">.</span><span class="na">iterate</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="o">);</span> <span class="c1">// 0, 1, 2, 3, ...</span>

<span class="c1">// Finite iterate (Java 9+)</span>
<span class="nc">Stream</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">first10</span> <span class="o">=</span> <span class="nc">Stream</span><span class="o">.</span><span class="na">iterate</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="o">,</span> <span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="o">);</span>
</code></pre></div></div>

<hr />

<h2 id="intermediate-operations">Intermediate operations</h2>

<p>These are lazy — they return a new stream and don’t execute until a terminal operation is called.</p>

<h3 id="filter--keep-elements-matching-a-predicate"><code class="language-plaintext highlighter-rouge">filter</code> — keep elements matching a predicate</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">evens</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
</code></pre></div></div>

<h3 id="map--transform-each-element"><code class="language-plaintext highlighter-rouge">map</code> — transform each element</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">upperNames</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="nl">String:</span><span class="o">:</span><span class="n">toUpperCase</span><span class="o">)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>

<span class="c1">// Map to a different type</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">lengths</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="nl">String:</span><span class="o">:</span><span class="n">length</span><span class="o">)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
</code></pre></div></div>

<h3 id="flatmap--flatten-a-stream-of-streams"><code class="language-plaintext highlighter-rouge">flatMap</code> — flatten a stream of streams</h3>

<p>Use when each element maps to multiple elements. <code class="language-plaintext highlighter-rouge">map</code> would give you a <code class="language-plaintext highlighter-rouge">Stream&lt;List&lt;T&gt;&gt;</code>; <code class="language-plaintext highlighter-rouge">flatMap</code> flattens it to <code class="language-plaintext highlighter-rouge">Stream&lt;T&gt;</code>.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;&gt;</span> <span class="n">nested</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">),</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">3</span><span class="o">,</span> <span class="mi">4</span><span class="o">),</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">5</span><span class="o">));</span>

<span class="c1">// map gives Stream&lt;List&lt;Integer&gt;&gt; — not what we want</span>
<span class="c1">// flatMap gives Stream&lt;Integer&gt;</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">flat</span> <span class="o">=</span> <span class="n">nested</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">flatMap</span><span class="o">(</span><span class="nl">Collection:</span><span class="o">:</span><span class="n">stream</span><span class="o">)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
<span class="c1">// [1, 2, 3, 4, 5]</span>
</code></pre></div></div>

<p>Another common use — splitting strings into words:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">sentences</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="s">"hello world"</span><span class="o">,</span> <span class="s">"foo bar"</span><span class="o">);</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">words</span> <span class="o">=</span> <span class="n">sentences</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">flatMap</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="nc">Arrays</span><span class="o">.</span><span class="na">stream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">" "</span><span class="o">)))</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
<span class="c1">// ["hello", "world", "foo", "bar"]</span>
</code></pre></div></div>

<h3 id="sorted--sort-elements"><code class="language-plaintext highlighter-rouge">sorted</code> — sort elements</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Natural order</span>
<span class="n">list</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">sorted</span><span class="o">()</span>

<span class="c1">// Custom comparator</span>
<span class="n">list</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">sorted</span><span class="o">(</span><span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">))</span>

<span class="c1">// Descending</span>
<span class="n">list</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">sorted</span><span class="o">(</span><span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">).</span><span class="na">reversed</span><span class="o">())</span>
</code></pre></div></div>

<h3 id="distinct--remove-duplicates"><code class="language-plaintext highlighter-rouge">distinct</code> — remove duplicates</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">unique</span> <span class="o">=</span> <span class="nc">List</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">2</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">3</span><span class="o">,</span> <span class="mi">3</span><span class="o">).</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">distinct</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
<span class="c1">// [1, 2, 3]</span>
</code></pre></div></div>

<h3 id="limit-and-skip"><code class="language-plaintext highlighter-rouge">limit</code> and <code class="language-plaintext highlighter-rouge">skip</code></h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// First 5 elements</span>
<span class="n">stream</span><span class="o">.</span><span class="na">limit</span><span class="o">(</span><span class="mi">5</span><span class="o">)</span>

<span class="c1">// Skip first 5, take the rest</span>
<span class="n">stream</span><span class="o">.</span><span class="na">skip</span><span class="o">(</span><span class="mi">5</span><span class="o">)</span>

<span class="c1">// Pagination: page 2, size 10</span>
<span class="n">stream</span><span class="o">.</span><span class="na">skip</span><span class="o">(</span><span class="mi">10</span><span class="o">).</span><span class="na">limit</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span>
</code></pre></div></div>

<h3 id="peek--inspect-elements-without-consuming-the-stream"><code class="language-plaintext highlighter-rouge">peek</code> — inspect elements without consuming the stream</h3>

<p>Useful for debugging. Does not alter the stream.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">list</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="o">)</span>
    <span class="o">.</span><span class="na">peek</span><span class="o">(</span><span class="n">n</span> <span class="o">-&gt;</span> <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"after filter: "</span> <span class="o">+</span> <span class="n">n</span><span class="o">))</span>
    <span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span> <span class="o">*</span> <span class="mi">2</span><span class="o">)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
</code></pre></div></div>

<hr />

<h2 id="terminal-operations">Terminal operations</h2>

<p>These trigger the pipeline to execute and produce a result. After calling one, the stream is consumed.</p>

<h3 id="collect--gather-results-into-a-collection"><code class="language-plaintext highlighter-rouge">collect</code> — gather results into a collection</h3>

<p>The most common terminal operation. Takes a <code class="language-plaintext highlighter-rouge">Collector</code> — covered in the next section.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
<span class="nc">Set</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">set</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toSet</span><span class="o">());</span>
</code></pre></div></div>

<h3 id="foreach--consume-each-element"><code class="language-plaintext highlighter-rouge">forEach</code> — consume each element</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">forEach</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">::</span><span class="n">println</span><span class="o">);</span>
</code></pre></div></div>

<p>Note: <code class="language-plaintext highlighter-rouge">forEach</code> does not guarantee order on parallel streams. Use <code class="language-plaintext highlighter-rouge">forEachOrdered</code> if order matters.</p>

<h3 id="count"><code class="language-plaintext highlighter-rouge">count</code></h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">long</span> <span class="n">count</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">filter</span><span class="o">(</span><span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span><span class="o">.</span><span class="na">startsWith</span><span class="o">(</span><span class="s">"A"</span><span class="o">)).</span><span class="na">count</span><span class="o">();</span>
</code></pre></div></div>

<h3 id="findfirst-and-findany"><code class="language-plaintext highlighter-rouge">findFirst</code> and <code class="language-plaintext highlighter-rouge">findAny</code></h3>

<p>Both return an <code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code>. <code class="language-plaintext highlighter-rouge">findFirst</code> returns the first element in encounter order; <code class="language-plaintext highlighter-rouge">findAny</code> may return any element (faster on parallel streams).</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Optional</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">first</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">n</span> <span class="o">-&gt;</span> <span class="n">n</span><span class="o">.</span><span class="na">length</span><span class="o">()</span> <span class="o">&gt;</span> <span class="mi">3</span><span class="o">)</span>
    <span class="o">.</span><span class="na">findFirst</span><span class="o">();</span>

<span class="n">first</span><span class="o">.</span><span class="na">ifPresent</span><span class="o">(</span><span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">::</span><span class="n">println</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">val</span> <span class="o">=</span> <span class="n">first</span><span class="o">.</span><span class="na">orElse</span><span class="o">(</span><span class="s">"none"</span><span class="o">);</span>
</code></pre></div></div>

<h3 id="anymatch-allmatch-nonematch"><code class="language-plaintext highlighter-rouge">anyMatch</code>, <code class="language-plaintext highlighter-rouge">allMatch</code>, <code class="language-plaintext highlighter-rouge">noneMatch</code></h3>

<p>Short-circuit — stop as soon as the answer is known.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">boolean</span> <span class="n">hasAdult</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">anyMatch</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">getAge</span><span class="o">()</span> <span class="o">&gt;=</span> <span class="mi">18</span><span class="o">);</span>
<span class="kt">boolean</span> <span class="n">allAdults</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">allMatch</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">getAge</span><span class="o">()</span> <span class="o">&gt;=</span> <span class="mi">18</span><span class="o">);</span>
<span class="kt">boolean</span> <span class="n">noneMinor</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">noneMatch</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">getAge</span><span class="o">()</span> <span class="o">&lt;</span> <span class="mi">18</span><span class="o">);</span>
</code></pre></div></div>

<h3 id="min-and-max"><code class="language-plaintext highlighter-rouge">min</code> and <code class="language-plaintext highlighter-rouge">max</code></h3>

<p>Return <code class="language-plaintext highlighter-rouge">Optional&lt;T&gt;</code>.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Optional</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">youngest</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">min</span><span class="o">(</span><span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">));</span>

<span class="nc">Optional</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">maxVal</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">max</span><span class="o">(</span><span class="nl">Integer:</span><span class="o">:</span><span class="n">compare</span><span class="o">);</span>
</code></pre></div></div>

<h3 id="reduce--fold-elements-into-a-single-value"><code class="language-plaintext highlighter-rouge">reduce</code> — fold elements into a single value</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Sum</span>
<span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="nl">Integer:</span><span class="o">:</span><span class="n">sum</span><span class="o">);</span>

<span class="c1">// Product</span>
<span class="kt">int</span> <span class="n">product</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span><span class="o">);</span>

<span class="c1">// Without identity — returns Optional</span>
<span class="nc">Optional</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">max</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">reduce</span><span class="o">(</span><span class="nl">Integer:</span><span class="o">:</span><span class="n">max</span><span class="o">);</span>
</code></pre></div></div>

<hr />

<h2 id="collectors">Collectors</h2>

<p><code class="language-plaintext highlighter-rouge">Collectors</code> is a utility class with factory methods for common collection strategies.</p>

<h3 id="tolist-toset-tounmodifiablelist"><code class="language-plaintext highlighter-rouge">toList</code>, <code class="language-plaintext highlighter-rouge">toSet</code>, <code class="language-plaintext highlighter-rouge">toUnmodifiableList</code></h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">list</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
<span class="nc">Set</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">set</span>  <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toSet</span><span class="o">());</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">immutable</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toUnmodifiableList</span><span class="o">());</span>
</code></pre></div></div>

<h3 id="tomap"><code class="language-plaintext highlighter-rouge">toMap</code></h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Map from name to age</span>
<span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">nameToAge</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toMap</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">,</span> <span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">));</span>

<span class="c1">// Handle duplicate keys with a merge function</span>
<span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">nameToAge</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toMap</span><span class="o">(</span>
        <span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">,</span>
        <span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">,</span>
        <span class="o">(</span><span class="n">existing</span><span class="o">,</span> <span class="n">newVal</span><span class="o">)</span> <span class="o">-&gt;</span> <span class="n">existing</span>  <span class="c1">// keep existing on collision</span>
    <span class="o">));</span>
</code></pre></div></div>

<h3 id="groupingby--group-elements-by-a-classifier"><code class="language-plaintext highlighter-rouge">groupingBy</code> — group elements by a classifier</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Group students by department</span>
<span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;&gt;</span> <span class="n">byDept</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">groupingBy</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getDepartment</span><span class="o">));</span>

<span class="c1">// Group and count</span>
<span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Long</span><span class="o">&gt;</span> <span class="n">countByDept</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">groupingBy</span><span class="o">(</span>
        <span class="nl">Student:</span><span class="o">:</span><span class="n">getDepartment</span><span class="o">,</span>
        <span class="nc">Collectors</span><span class="o">.</span><span class="na">counting</span><span class="o">()</span>
    <span class="o">));</span>

<span class="c1">// Group and collect only names</span>
<span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;&gt;</span> <span class="n">namesByDept</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">groupingBy</span><span class="o">(</span>
        <span class="nl">Student:</span><span class="o">:</span><span class="n">getDepartment</span><span class="o">,</span>
        <span class="nc">Collectors</span><span class="o">.</span><span class="na">mapping</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">,</span> <span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">())</span>
    <span class="o">));</span>
</code></pre></div></div>

<h3 id="partitioningby--split-into-two-groups-truefalse"><code class="language-plaintext highlighter-rouge">partitioningBy</code> — split into two groups (true/false)</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">Boolean</span><span class="o">,</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;&gt;</span> <span class="n">partition</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">partitioningBy</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">getAge</span><span class="o">()</span> <span class="o">&gt;=</span> <span class="mi">18</span><span class="o">));</span>

<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">adults</span> <span class="o">=</span> <span class="n">partition</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="nc">List</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">minors</span> <span class="o">=</span> <span class="n">partition</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span>
</code></pre></div></div>

<h3 id="joining--concatenate-strings"><code class="language-plaintext highlighter-rouge">joining</code> — concatenate strings</h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">String</span> <span class="n">result</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">joining</span><span class="o">());</span>
<span class="c1">// "AliceBobCharlie"</span>

<span class="nc">String</span> <span class="n">result</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">joining</span><span class="o">(</span><span class="s">", "</span><span class="o">));</span>
<span class="c1">// "Alice, Bob, Charlie"</span>

<span class="nc">String</span> <span class="n">result</span> <span class="o">=</span> <span class="n">names</span><span class="o">.</span><span class="na">stream</span><span class="o">().</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">joining</span><span class="o">(</span><span class="s">", "</span><span class="o">,</span> <span class="s">"["</span><span class="o">,</span> <span class="s">"]"</span><span class="o">));</span>
<span class="c1">// "[Alice, Bob, Charlie]"</span>
</code></pre></div></div>

<h3 id="counting-summingint-averagingint"><code class="language-plaintext highlighter-rouge">counting</code>, <code class="language-plaintext highlighter-rouge">summingInt</code>, <code class="language-plaintext highlighter-rouge">averagingInt</code></h3>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">long</span> <span class="n">count</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">counting</span><span class="o">());</span>
<span class="kt">int</span> <span class="n">total</span>  <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">summingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">));</span>
<span class="kt">double</span> <span class="n">avg</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">averagingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">));</span>
</code></pre></div></div>

<hr />

<h2 id="primitive-streams">Primitive streams</h2>

<p>For <code class="language-plaintext highlighter-rouge">int</code>, <code class="language-plaintext highlighter-rouge">long</code>, and <code class="language-plaintext highlighter-rouge">double</code>, use <code class="language-plaintext highlighter-rouge">IntStream</code>, <code class="language-plaintext highlighter-rouge">LongStream</code>, <code class="language-plaintext highlighter-rouge">DoubleStream</code> to avoid boxing overhead. They have extra methods like <code class="language-plaintext highlighter-rouge">sum()</code>, <code class="language-plaintext highlighter-rouge">average()</code>, <code class="language-plaintext highlighter-rouge">range()</code>.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Sum of 1 to 100</span>
<span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="nc">IntStream</span><span class="o">.</span><span class="na">rangeClosed</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="mi">100</span><span class="o">).</span><span class="na">sum</span><span class="o">();</span>

<span class="c1">// Average age</span>
<span class="nc">OptionalDouble</span> <span class="n">avg</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">mapToInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getAge</span><span class="o">)</span>
    <span class="o">.</span><span class="na">average</span><span class="o">();</span>

<span class="c1">// Box back to Stream&lt;Integer&gt; if needed</span>
<span class="nc">Stream</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">boxed</span> <span class="o">=</span> <span class="nc">IntStream</span><span class="o">.</span><span class="na">range</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="mi">10</span><span class="o">).</span><span class="na">boxed</span><span class="o">();</span>
</code></pre></div></div>

<hr />

<h2 id="common-patterns">Common patterns</h2>

<p><strong>Filter then transform:</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">result</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">getAge</span><span class="o">()</span> <span class="o">&gt;</span> <span class="mi">20</span><span class="o">)</span>
    <span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getName</span><span class="o">)</span>
    <span class="o">.</span><span class="na">sorted</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
</code></pre></div></div>

<p><strong>Frequency map (word count):</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Map</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Long</span><span class="o">&gt;</span> <span class="n">freq</span> <span class="o">=</span> <span class="n">words</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">groupingBy</span><span class="o">(</span><span class="n">w</span> <span class="o">-&gt;</span> <span class="n">w</span><span class="o">,</span> <span class="nc">Collectors</span><span class="o">.</span><span class="na">counting</span><span class="o">()));</span>
</code></pre></div></div>

<p><strong>Flatten and deduplicate:</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">Set</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">allTags</span> <span class="o">=</span> <span class="n">posts</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">flatMap</span><span class="o">(</span><span class="n">p</span> <span class="o">-&gt;</span> <span class="n">p</span><span class="o">.</span><span class="na">getTags</span><span class="o">().</span><span class="na">stream</span><span class="o">())</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toSet</span><span class="o">());</span>
</code></pre></div></div>

<p><strong>Top N elements:</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">List</span><span class="o">&lt;</span><span class="nc">Student</span><span class="o">&gt;</span> <span class="n">top3</span> <span class="o">=</span> <span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">sorted</span><span class="o">(</span><span class="nc">Comparator</span><span class="o">.</span><span class="na">comparingInt</span><span class="o">(</span><span class="nl">Student:</span><span class="o">:</span><span class="n">getScore</span><span class="o">).</span><span class="na">reversed</span><span class="o">())</span>
    <span class="o">.</span><span class="na">limit</span><span class="o">(</span><span class="mi">3</span><span class="o">)</span>
    <span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
</code></pre></div></div>

<p><strong>Check if a value exists and get it:</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">students</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="n">s</span><span class="o">.</span><span class="na">getName</span><span class="o">().</span><span class="na">equals</span><span class="o">(</span><span class="s">"Alice"</span><span class="o">))</span>
    <span class="o">.</span><span class="na">findFirst</span><span class="o">()</span>
    <span class="o">.</span><span class="na">ifPresent</span><span class="o">(</span><span class="n">s</span> <span class="o">-&gt;</span> <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getAge</span><span class="o">()));</span>
</code></pre></div></div>

<hr />

<h2 id="parallel-streams">Parallel streams</h2>

<p>Call <code class="language-plaintext highlighter-rouge">.parallelStream()</code> instead of <code class="language-plaintext highlighter-rouge">.stream()</code> to split work across threads. Useful for CPU-bound operations on large collections.</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">long</span> <span class="n">count</span> <span class="o">=</span> <span class="n">bigList</span><span class="o">.</span><span class="na">parallelStream</span><span class="o">()</span>
    <span class="o">.</span><span class="na">filter</span><span class="o">(</span><span class="n">expensiveOperation</span><span class="o">)</span>
    <span class="o">.</span><span class="na">count</span><span class="o">();</span>
</code></pre></div></div>

<p>Caveats:</p>
<ul>
  <li>Not always faster — parallelism has overhead. Benchmark before using.</li>
  <li>Order is not guaranteed unless you use <code class="language-plaintext highlighter-rouge">forEachOrdered</code> or <code class="language-plaintext highlighter-rouge">sorted</code>.</li>
  <li>Avoid stateful lambdas (e.g., modifying a shared variable) — they cause race conditions.</li>
</ul>

<hr />

<h2 id="quick-reference">Quick reference</h2>

<table>
  <thead>
    <tr>
      <th>Operation</th>
      <th>Type</th>
      <th>What it does</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">filter(pred)</code></td>
      <td>Intermediate</td>
      <td>Keep matching elements</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">map(fn)</code></td>
      <td>Intermediate</td>
      <td>Transform each element</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">flatMap(fn)</code></td>
      <td>Intermediate</td>
      <td>Transform and flatten</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">sorted(cmp)</code></td>
      <td>Intermediate</td>
      <td>Sort elements</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">distinct()</code></td>
      <td>Intermediate</td>
      <td>Remove duplicates</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">limit(n)</code></td>
      <td>Intermediate</td>
      <td>Take first n</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">skip(n)</code></td>
      <td>Intermediate</td>
      <td>Skip first n</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">peek(fn)</code></td>
      <td>Intermediate</td>
      <td>Inspect without consuming</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">collect(c)</code></td>
      <td>Terminal</td>
      <td>Gather into collection</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">forEach(fn)</code></td>
      <td>Terminal</td>
      <td>Consume each element</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">count()</code></td>
      <td>Terminal</td>
      <td>Count elements</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">findFirst()</code></td>
      <td>Terminal</td>
      <td>First element as Optional</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">anyMatch(pred)</code></td>
      <td>Terminal</td>
      <td>Short-circuit OR</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">allMatch(pred)</code></td>
      <td>Terminal</td>
      <td>Short-circuit AND</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">reduce(id, fn)</code></td>
      <td>Terminal</td>
      <td>Fold into single value</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">min(cmp)</code> / <code class="language-plaintext highlighter-rouge">max(cmp)</code></td>
      <td>Terminal</td>
      <td>Minimum / maximum as Optional</td>
    </tr>
  </tbody>
</table>]]></content><author><name>Seroze</name></author><category term="java" /><category term="java" /><category term="streams" /><category term="functional-programming" /><summary type="html"><![CDATA[A Stream is not a data structure — it’s a pipeline. You describe what you want, and the stream figures out how to compute it lazily.]]></summary></entry><entry><title type="html">Setting Up Python Projects — uv, pip, and pytest</title><link href="/python-project-setup/" rel="alternate" type="text/html" title="Setting Up Python Projects — uv, pip, and pytest" /><published>2026-06-18T18:30:00+00:00</published><updated>2026-06-18T18:30:00+00:00</updated><id>/python-project-setup</id><content type="html" xml:base="/python-project-setup/"><![CDATA[<p><em>Python has historically had too many ways to manage dependencies. This post covers the modern approach with <code class="language-plaintext highlighter-rouge">uv</code>, the pip fallback, and how to run tests with pytest.</em></p>

<hr />

<h2 id="creating-a-new-project-with-uv">Creating a new project with <code class="language-plaintext highlighter-rouge">uv</code></h2>

<p><code class="language-plaintext highlighter-rouge">uv</code> is a fast Python package manager (written in Rust by Astral, the team behind Ruff). It replaces <code class="language-plaintext highlighter-rouge">pip</code>, <code class="language-plaintext highlighter-rouge">venv</code>, <code class="language-plaintext highlighter-rouge">pip-tools</code>, and partly <code class="language-plaintext highlighter-rouge">poetry</code> with a single tool.</p>

<p>Install uv:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="nt">-LsSf</span> https://astral.sh/uv/install.sh | sh
<span class="c"># or</span>
pip <span class="nb">install </span>uv
</code></pre></div></div>

<p>Create a new project:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv init my-project
<span class="nb">cd </span>my-project
</code></pre></div></div>

<p>This scaffolds:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>my-project/
├── pyproject.toml       # project metadata and dependencies
├── README.md
├── .python-version      # pins the Python version for this project
├── .gitignore
└── src/
    └── my_project/
        └── __init__.py
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">uv init</code> also creates a virtual environment at <code class="language-plaintext highlighter-rouge">.venv/</code> automatically on first use.</p>

<hr />

<h2 id="typical-project-structure">Typical project structure</h2>

<p>For anything beyond a one-file script, use the <strong>src layout</strong>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>my-project/
├── pyproject.toml
├── README.md
├── .gitignore
├── .python-version
├── src/
│   └── my_project/          # your package (underscores, not hyphens)
│       ├── __init__.py
│       ├── main.py
│       ├── models/
│       │   ├── __init__.py
│       │   └── user.py
│       └── services/
│           ├── __init__.py
│           └── auth.py
└── tests/
    ├── conftest.py           # shared fixtures
    ├── test_main.py
    ├── models/
    │   └── test_user.py
    └── services/
        └── test_auth.py
</code></pre></div></div>

<p><strong>Why <code class="language-plaintext highlighter-rouge">src/</code> layout?</strong> Without it, <code class="language-plaintext highlighter-rouge">import my_project</code> in tests would find the local directory instead of the installed package — which can hide import errors that only show up in production. The <code class="language-plaintext highlighter-rouge">src/</code> layout forces the package to be installed before it can be imported.</p>

<p><strong>Test files mirror the source structure</strong> — same as Java/Gradle. <code class="language-plaintext highlighter-rouge">src/my_project/models/user.py</code> → <code class="language-plaintext highlighter-rouge">tests/models/test_user.py</code>. Pytest discovers test files by looking for files named <code class="language-plaintext highlighter-rouge">test_*.py</code> or <code class="language-plaintext highlighter-rouge">*_test.py</code>.</p>

<hr />

<h2 id="python-naming-conventions">Python naming conventions</h2>

<table>
  <thead>
    <tr>
      <th>Construct</th>
      <th>Convention</th>
      <th>Example</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Module / file</td>
      <td><code class="language-plaintext highlighter-rouge">snake_case</code></td>
      <td><code class="language-plaintext highlighter-rouge">user_service.py</code>, <code class="language-plaintext highlighter-rouge">auth_utils.py</code></td>
    </tr>
    <tr>
      <td>Package / directory</td>
      <td><code class="language-plaintext highlighter-rouge">snake_case</code></td>
      <td><code class="language-plaintext highlighter-rouge">my_project/</code>, <code class="language-plaintext highlighter-rouge">http_client/</code></td>
    </tr>
    <tr>
      <td>Class</td>
      <td><code class="language-plaintext highlighter-rouge">PascalCase</code></td>
      <td><code class="language-plaintext highlighter-rouge">UserService</code>, <code class="language-plaintext highlighter-rouge">HttpClient</code></td>
    </tr>
    <tr>
      <td>Function / method</td>
      <td><code class="language-plaintext highlighter-rouge">snake_case</code></td>
      <td><code class="language-plaintext highlighter-rouge">get_user()</code>, <code class="language-plaintext highlighter-rouge">parse_response()</code></td>
    </tr>
    <tr>
      <td>Variable</td>
      <td><code class="language-plaintext highlighter-rouge">snake_case</code></td>
      <td><code class="language-plaintext highlighter-rouge">user_id</code>, <code class="language-plaintext highlighter-rouge">max_retries</code></td>
    </tr>
    <tr>
      <td>Constant</td>
      <td><code class="language-plaintext highlighter-rouge">UPPER_SNAKE_CASE</code></td>
      <td><code class="language-plaintext highlighter-rouge">MAX_CONNECTIONS</code>, <code class="language-plaintext highlighter-rouge">DEFAULT_TIMEOUT</code></td>
    </tr>
    <tr>
      <td>Private method / attribute</td>
      <td><code class="language-plaintext highlighter-rouge">_leading_underscore</code></td>
      <td><code class="language-plaintext highlighter-rouge">_validate()</code>, <code class="language-plaintext highlighter-rouge">_cache</code></td>
    </tr>
    <tr>
      <td>Name-mangled (class-private)</td>
      <td><code class="language-plaintext highlighter-rouge">__double_leading</code></td>
      <td><code class="language-plaintext highlighter-rouge">__secret</code>, <code class="language-plaintext highlighter-rouge">__init_state()</code></td>
    </tr>
    <tr>
      <td>Type alias</td>
      <td><code class="language-plaintext highlighter-rouge">PascalCase</code></td>
      <td><code class="language-plaintext highlighter-rouge">UserId = int</code>, <code class="language-plaintext highlighter-rouge">ResponseMap = dict[str, Any]</code></td>
    </tr>
    <tr>
      <td>Dunder / magic method</td>
      <td><code class="language-plaintext highlighter-rouge">__double_both__</code></td>
      <td><code class="language-plaintext highlighter-rouge">__init__</code>, <code class="language-plaintext highlighter-rouge">__repr__</code>, <code class="language-plaintext highlighter-rouge">__len__</code></td>
    </tr>
  </tbody>
</table>

<p>These follow <a href="https://peps.python.org/pep-0008/">PEP 8</a>, the official Python style guide.</p>

<hr />

<h2 id="googles-python-conventions">Google’s Python conventions</h2>

<p><a href="https://google.github.io/styleguide/pyguide.html">Google’s Python Style Guide</a> builds on PEP 8 but adds a few opinions of its own. These are the ones worth internalizing:</p>

<h3 id="naming-the-google-way">Naming, the Google way</h3>

<p>Google spells out the casing rules explicitly. They line up with PEP 8 above, but the guide phrases them as a table you can memorize:</p>

<table>
  <thead>
    <tr>
      <th>Type</th>
      <th>Convention</th>
      <th>Example</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Module</td>
      <td><code class="language-plaintext highlighter-rouge">lower_with_under</code></td>
      <td><code class="language-plaintext highlighter-rouge">socket_server</code></td>
    </tr>
    <tr>
      <td>Package</td>
      <td><code class="language-plaintext highlighter-rouge">lower_with_under</code></td>
      <td><code class="language-plaintext highlighter-rouge">my_package</code></td>
    </tr>
    <tr>
      <td>Class / Exception</td>
      <td><code class="language-plaintext highlighter-rouge">CapWords</code> (PascalCase)</td>
      <td><code class="language-plaintext highlighter-rouge">HttpClient</code>, <code class="language-plaintext highlighter-rouge">ValueError</code></td>
    </tr>
    <tr>
      <td>Function / Method</td>
      <td><code class="language-plaintext highlighter-rouge">lower_with_under()</code></td>
      <td><code class="language-plaintext highlighter-rouge">send_request()</code></td>
    </tr>
    <tr>
      <td>Global / Class constant</td>
      <td><code class="language-plaintext highlighter-rouge">CAPS_WITH_UNDER</code></td>
      <td><code class="language-plaintext highlighter-rouge">MAX_RETRIES</code></td>
    </tr>
    <tr>
      <td>Variable / Parameter</td>
      <td><code class="language-plaintext highlighter-rouge">lower_with_under</code></td>
      <td><code class="language-plaintext highlighter-rouge">retry_count</code></td>
    </tr>
    <tr>
      <td>Instance var (public)</td>
      <td><code class="language-plaintext highlighter-rouge">lower_with_under</code></td>
      <td><code class="language-plaintext highlighter-rouge">self.user_id</code></td>
    </tr>
    <tr>
      <td>Instance var (protected)</td>
      <td><code class="language-plaintext highlighter-rouge">_lower_with_under</code></td>
      <td><code class="language-plaintext highlighter-rouge">self._cache</code></td>
    </tr>
  </tbody>
</table>

<p>Google explicitly <strong>avoids</strong> <code class="language-plaintext highlighter-rouge">__double_leading_underscore</code> for “private” attributes — they prefer a single underscore, because name mangling is rarely worth the friction.</p>

<h3 id="things-google-is-opinionated-about">Things Google is opinionated about</h3>

<ul>
  <li><strong>No single-character names</strong> except for counters/iterators (<code class="language-plaintext highlighter-rouge">i</code>, <code class="language-plaintext highlighter-rouge">j</code>), <code class="language-plaintext highlighter-rouge">e</code> in <code class="language-plaintext highlighter-rouge">except</code> clauses, and <code class="language-plaintext highlighter-rouge">f</code> for file handles. Avoid <code class="language-plaintext highlighter-rouge">l</code>, <code class="language-plaintext highlighter-rouge">O</code>, <code class="language-plaintext highlighter-rouge">I</code> — they look like <code class="language-plaintext highlighter-rouge">1</code> and <code class="language-plaintext highlighter-rouge">0</code>.</li>
  <li><strong>No “dunder” naming for your own modules</strong> — names like <code class="language-plaintext highlighter-rouge">__author__</code> are discouraged.</li>
  <li><strong>Prefer descriptive names over abbreviations.</strong> <code class="language-plaintext highlighter-rouge">error_count</code>, not <code class="language-plaintext highlighter-rouge">err_cnt</code>.</li>
  <li><strong><code class="language-plaintext highlighter-rouge">CapWords</code> for class names even when they’re acronyms</strong> — <code class="language-plaintext highlighter-rouge">HttpServer</code>, not <code class="language-plaintext highlighter-rouge">HTTPServer</code>.</li>
  <li><strong>Module names match the file name</strong> — keep them short and <code class="language-plaintext highlighter-rouge">lower_with_under</code>.</li>
  <li><strong>Use one statement per line</strong>, and keep lines ≤ 80 chars (PEP 8 allows 79; Google says 80).</li>
</ul>

<h3 id="docstrings">Docstrings</h3>

<p>Google has a distinctive docstring style — sectioned with <code class="language-plaintext highlighter-rouge">Args:</code>, <code class="language-plaintext highlighter-rouge">Returns:</code>, <code class="language-plaintext highlighter-rouge">Raises:</code>:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fetch_user</span><span class="p">(</span><span class="n">user_id</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">retries</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">3</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">User</span><span class="p">:</span>
    <span class="s">"""Fetches a user by ID.

    Args:
        user_id: The unique identifier of the user.
        retries: Number of times to retry on failure.

    Returns:
        The User object matching the given ID.

    Raises:
        UserNotFoundError: If no user exists with that ID.
    """</span>
</code></pre></div></div>

<p>This is the “Google style” you’ll see picked up by tools like Sphinx’s Napoleon extension. The alternative is NumPy or reST style — pick one and stay consistent across the project.</p>

<hr />

<h2 id="pyprojecttoml--the-modern-config-file"><code class="language-plaintext highlighter-rouge">pyproject.toml</code> — the modern config file</h2>

<p><code class="language-plaintext highlighter-rouge">pyproject.toml</code> is the single file for project metadata, dependencies, and tool config. It replaces <code class="language-plaintext highlighter-rouge">setup.py</code>, <code class="language-plaintext highlighter-rouge">setup.cfg</code>, and <code class="language-plaintext highlighter-rouge">requirements.txt</code> for most purposes.</p>

<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[project]</span>
<span class="py">name</span> <span class="p">=</span> <span class="s">"my-project"</span>
<span class="py">version</span> <span class="p">=</span> <span class="s">"0.1.0"</span>
<span class="py">description</span> <span class="p">=</span> <span class="s">"A short description"</span>
<span class="py">requires-python</span> <span class="p">=</span> <span class="py">"&gt;</span><span class="p">=</span><span class="mf">3.11</span><span class="s">"</span><span class="err">
</span><span class="py">dependencies</span> <span class="p">=</span> <span class="p">[</span>
    <span class="py">"requests&gt;</span><span class="p">=</span><span class="mf">2.31</span><span class="err">.</span><span class="mi">0</span><span class="s">",</span><span class="err">
</span>    <span class="py">"pydantic&gt;</span><span class="p">=</span><span class="mf">2.0</span><span class="s">",</span><span class="err">
</span><span class="p">]</span>

<span class="nn">[project.optional-dependencies]</span>
<span class="py">dev</span> <span class="p">=</span> <span class="p">[</span>
    <span class="py">"pytest&gt;</span><span class="p">=</span><span class="mf">8.0</span><span class="s">",</span><span class="err">
</span>    <span class="s">"pytest-cov"</span><span class="p">,</span>
    <span class="s">"ruff"</span><span class="p">,</span>
<span class="p">]</span>

<span class="nn">[build-system]</span>
<span class="py">requires</span> <span class="p">=</span> <span class="nn">["hatchling"]</span>
<span class="py">build-backend</span> <span class="p">=</span> <span class="s">"hatchling.build"</span>

<span class="nn">[tool.pytest.ini_options]</span>
<span class="py">testpaths</span> <span class="p">=</span> <span class="nn">["tests"]</span>
</code></pre></div></div>

<hr />

<h2 id="virtual-environments--why-they-matter">Virtual environments — why they matter</h2>

<p>A virtual environment is an isolated Python installation for your project. Without one, every project on your machine shares the same global packages — version conflicts are inevitable.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Create a venv manually</span>
python <span class="nt">-m</span> venv .venv

<span class="c"># Activate it (Linux/Mac)</span>
<span class="nb">source</span> .venv/bin/activate

<span class="c"># Activate it (Windows)</span>
.venv<span class="se">\S</span>cripts<span class="se">\a</span>ctivate

<span class="c"># You're now in the venv — pip install goes here, not system-wide</span>
<span class="o">(</span>my-project<span class="o">)</span> <span class="nv">$ </span>pip <span class="nb">install </span>requests
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">uv</code> manages the venv for you automatically — you rarely need to activate it manually.</p>

<hr />

<h2 id="managing-dependencies-with-uv">Managing dependencies with <code class="language-plaintext highlighter-rouge">uv</code></h2>

<h3 id="add-a-dependency">Add a dependency</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv add requests          <span class="c"># adds to [project.dependencies] in pyproject.toml</span>
uv add pytest <span class="nt">--dev</span>      <span class="c"># adds to dev dependencies</span>
uv add <span class="s2">"pydantic&gt;=2.0"</span>   <span class="c"># with version constraint</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">uv add</code> also updates <code class="language-plaintext highlighter-rouge">uv.lock</code> — the lockfile that pins every dependency’s exact version.</p>

<h3 id="install-all-dependencies-eg-after-cloning-a-repo">Install all dependencies (e.g. after cloning a repo)</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv <span class="nb">sync</span>                  <span class="c"># installs everything in pyproject.toml</span>
uv <span class="nb">sync</span> <span class="nt">--dev</span>            <span class="c"># includes dev dependencies too</span>
</code></pre></div></div>

<h3 id="remove-a-dependency">Remove a dependency</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv remove requests
</code></pre></div></div>

<h3 id="run-a-command-inside-the-project-environment">Run a command inside the project environment</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv run python src/my_project/main.py
uv run pytest
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">uv run</code> automatically uses the project’s venv without needing to activate it first.</p>

<h3 id="show-installed-packages">Show installed packages</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv pip list
</code></pre></div></div>

<hr />

<h2 id="managing-dependencies-with-pip-the-fallback">Managing dependencies with <code class="language-plaintext highlighter-rouge">pip</code> (the fallback)</h2>

<p>If you’re not using <code class="language-plaintext highlighter-rouge">uv</code>, the traditional approach uses <code class="language-plaintext highlighter-rouge">pip</code> and a <code class="language-plaintext highlighter-rouge">requirements.txt</code> file.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Create and activate a venv</span>
python <span class="nt">-m</span> venv .venv
<span class="nb">source</span> .venv/bin/activate

<span class="c"># Install packages</span>
pip <span class="nb">install </span>requests pydantic

<span class="c"># Save current environment to a file</span>
pip freeze <span class="o">&gt;</span> requirements.txt

<span class="c"># Install from requirements file (e.g. after cloning)</span>
pip <span class="nb">install</span> <span class="nt">-r</span> requirements.txt

<span class="c"># Install dev dependencies separately</span>
pip <span class="nb">install</span> <span class="nt">-r</span> requirements-dev.txt
</code></pre></div></div>

<p>A typical <code class="language-plaintext highlighter-rouge">requirements-dev.txt</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-r requirements.txt      # include production deps
pytest&gt;=8.0
pytest-cov
ruff
</code></pre></div></div>

<p><strong><code class="language-plaintext highlighter-rouge">pip freeze</code> vs <code class="language-plaintext highlighter-rouge">pyproject.toml</code>:</strong> <code class="language-plaintext highlighter-rouge">pip freeze</code> pins every transitive dependency including ones you didn’t explicitly ask for, which makes upgrades painful. <code class="language-plaintext highlighter-rouge">pyproject.toml</code> with <code class="language-plaintext highlighter-rouge">uv.lock</code> is cleaner — you declare direct dependencies, the lockfile handles the rest.</p>

<hr />

<h2 id="running-tests-with-pytest">Running tests with pytest</h2>

<p>Install pytest:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv add pytest <span class="nt">--dev</span>
<span class="c"># or</span>
pip <span class="nb">install </span>pytest
</code></pre></div></div>

<h3 id="basic-usage">Basic usage</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Run all tests</span>
pytest

<span class="c"># With verbose output (shows each test name)</span>
pytest <span class="nt">-v</span>

<span class="c"># Run a specific file</span>
pytest tests/test_main.py

<span class="c"># Run a specific test function</span>
pytest tests/test_main.py::test_add

<span class="c"># Run a specific test class</span>
pytest tests/test_main.py::TestCalculator

<span class="c"># Run a specific method inside a class</span>
pytest tests/test_main.py::TestCalculator::test_add
</code></pre></div></div>

<h3 id="filter-by-name-with--k">Filter by name with <code class="language-plaintext highlighter-rouge">-k</code></h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Run tests whose name contains "auth"</span>
pytest <span class="nt">-k</span> <span class="s2">"auth"</span>

<span class="c"># Run tests matching an expression</span>
pytest <span class="nt">-k</span> <span class="s2">"auth or login"</span>
pytest <span class="nt">-k</span> <span class="s2">"not slow"</span>
</code></pre></div></div>

<h3 id="failure-output">Failure output</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Short traceback (default)</span>
pytest

<span class="c"># Full traceback</span>
pytest <span class="nt">--tb</span><span class="o">=</span>long

<span class="c"># Just the error line, no traceback</span>
pytest <span class="nt">--tb</span><span class="o">=</span>line

<span class="c"># Stop after first failure</span>
pytest <span class="nt">-x</span>

<span class="c"># Stop after 3 failures</span>
pytest <span class="nt">--maxfail</span><span class="o">=</span>3
</code></pre></div></div>

<h3 id="coverage">Coverage</h3>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>uv add pytest-cov <span class="nt">--dev</span>

pytest <span class="nt">--cov</span><span class="o">=</span>src/my_project              <span class="c"># coverage for your package</span>
pytest <span class="nt">--cov</span><span class="o">=</span>src/my_project <span class="nt">--cov-report</span><span class="o">=</span>html   <span class="c"># generates htmlcov/index.html</span>
</code></pre></div></div>

<hr />

<h2 id="writing-tests">Writing tests</h2>

<p>Pytest doesn’t require test classes — plain functions work fine.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># tests/test_math.py
</span><span class="k">def</span> <span class="nf">test_add</span><span class="p">():</span>
    <span class="k">assert</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">==</span> <span class="mi">2</span>

<span class="k">def</span> <span class="nf">test_divide_by_zero</span><span class="p">():</span>
    <span class="k">with</span> <span class="n">pytest</span><span class="p">.</span><span class="n">raises</span><span class="p">(</span><span class="nb">ZeroDivisionError</span><span class="p">):</span>
        <span class="mi">1</span> <span class="o">/</span> <span class="mi">0</span>
</code></pre></div></div>

<h3 id="fixtures--shared-setup-and-teardown">Fixtures — shared setup and teardown</h3>

<p>Fixtures are functions that provide data or resources to tests. Pytest injects them by parameter name.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># tests/conftest.py  — fixtures here are available to all test files
</span><span class="kn">import</span> <span class="nn">pytest</span>
<span class="kn">from</span> <span class="nn">my_project.models.user</span> <span class="kn">import</span> <span class="n">User</span>

<span class="o">@</span><span class="n">pytest</span><span class="p">.</span><span class="n">fixture</span>
<span class="k">def</span> <span class="nf">sample_user</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">User</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">"Alice"</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>

<span class="o">@</span><span class="n">pytest</span><span class="p">.</span><span class="n">fixture</span>
<span class="k">def</span> <span class="nf">db_connection</span><span class="p">():</span>
    <span class="n">conn</span> <span class="o">=</span> <span class="n">create_test_db</span><span class="p">()</span>
    <span class="k">yield</span> <span class="n">conn</span>          <span class="c1"># test runs here
</span>    <span class="n">conn</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>        <span class="c1"># teardown runs after the test
</span></code></pre></div></div>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># tests/test_user.py
</span><span class="k">def</span> <span class="nf">test_user_name</span><span class="p">(</span><span class="n">sample_user</span><span class="p">):</span>      <span class="c1"># pytest injects sample_user automatically
</span>    <span class="k">assert</span> <span class="n">sample_user</span><span class="p">.</span><span class="n">name</span> <span class="o">==</span> <span class="s">"Alice"</span>

<span class="k">def</span> <span class="nf">test_user_age</span><span class="p">(</span><span class="n">sample_user</span><span class="p">):</span>
    <span class="k">assert</span> <span class="n">sample_user</span><span class="p">.</span><span class="n">age</span> <span class="o">==</span> <span class="mi">30</span>
</code></pre></div></div>

<h3 id="parametrize--run-one-test-with-multiple-inputs">Parametrize — run one test with multiple inputs</h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pytest</span>

<span class="o">@</span><span class="n">pytest</span><span class="p">.</span><span class="n">mark</span><span class="p">.</span><span class="n">parametrize</span><span class="p">(</span><span class="s">"a, b, expected"</span><span class="p">,</span> <span class="p">[</span>
    <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
    <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
<span class="p">])</span>
<span class="k">def</span> <span class="nf">test_add</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span>
    <span class="k">assert</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="o">==</span> <span class="n">expected</span>
</code></pre></div></div>

<p>This runs <code class="language-plaintext highlighter-rouge">test_add</code> three times with different inputs and reports each separately.</p>

<hr />

<h2 id="how-python-import-resolution-actually-works-and-why-src-requires-installing">How Python import resolution actually works (and why <code class="language-plaintext highlighter-rouge">src/</code> requires installing)</h2>

<p>When you write <code class="language-plaintext highlighter-rouge">from cat_images.client import CatClient</code>, Python takes the first segment <code class="language-plaintext highlighter-rouge">cat_images</code> and looks for a directory with that exact name inside each entry in <code class="language-plaintext highlighter-rouge">sys.path</code>. It does <strong>not</strong> search recursively.</p>

<p>So if your project root is in <code class="language-plaintext highlighter-rouge">sys.path</code>, Python looks for <code class="language-plaintext highlighter-rouge">&lt;project-root&gt;/cat_images/</code> — which doesn’t exist. The actual package lives at <code class="language-plaintext highlighter-rouge">&lt;project-root&gt;/src/cat_images/</code>. That <code class="language-plaintext highlighter-rouge">src/</code> layer in between is what breaks the import.</p>

<p><strong>Why <code class="language-plaintext highlighter-rouge">from src.cat_images.client import ...</code> works without installing</strong></p>

<p>Because <code class="language-plaintext highlighter-rouge">src</code> is a real directory sitting directly in the project root. Python finds <code class="language-plaintext highlighter-rouge">src/</code> → <code class="language-plaintext highlighter-rouge">cat_images/</code> → <code class="language-plaintext highlighter-rouge">client.py</code> by traversing the import path segments. It’s treating <code class="language-plaintext highlighter-rouge">src</code> as a plain namespace, not a package boundary. It works, but it’s an ugly import path and the wrong approach.</p>

<p><strong>Why <code class="language-plaintext highlighter-rouge">uv pip install -e .</code> fixes it</strong></p>

<p>An editable install reads <code class="language-plaintext highlighter-rouge">pyproject.toml</code>, sees the package source is in <code class="language-plaintext highlighter-rouge">src/</code>, and registers <code class="language-plaintext highlighter-rouge">src/</code> itself as a path in the venv’s <code class="language-plaintext highlighter-rouge">site-packages</code>. Now Python can find <code class="language-plaintext highlighter-rouge">cat_images</code> directly. This is the intended workflow for the <code class="language-plaintext highlighter-rouge">src/</code> layout — it forces you to install before importing as a proper package, which prevents accidentally importing from your working tree instead of the installed package.</p>

<p><strong>Why VSCode still warns after installing</strong></p>

<p>Pylance (VSCode’s type checker) does static analysis — it doesn’t execute the venv to discover editable install paths the way the Python runtime does. You need to tell it explicitly where to look. Add this to <code class="language-plaintext highlighter-rouge">.vscode/settings.json</code>:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"python.analysis.extraPaths"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"src"</span><span class="p">]</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>This tells Pylance to also look in <code class="language-plaintext highlighter-rouge">src/</code> when resolving imports, matching what the editable install does at runtime.</p>

<hr />

<h2 id="uv-vs-pip--when-to-use-which"><code class="language-plaintext highlighter-rouge">uv</code> vs <code class="language-plaintext highlighter-rouge">pip</code> — when to use which</h2>

<table>
  <thead>
    <tr>
      <th> </th>
      <th><code class="language-plaintext highlighter-rouge">uv</code></th>
      <th><code class="language-plaintext highlighter-rouge">pip</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Speed</td>
      <td>Very fast (written in Rust)</td>
      <td>Slower</td>
    </tr>
    <tr>
      <td>Lockfile</td>
      <td><code class="language-plaintext highlighter-rouge">uv.lock</code> — exact reproducible installs</td>
      <td>None (use <code class="language-plaintext highlighter-rouge">pip freeze</code>)</td>
    </tr>
    <tr>
      <td>Config file</td>
      <td><code class="language-plaintext highlighter-rouge">pyproject.toml</code></td>
      <td><code class="language-plaintext highlighter-rouge">requirements.txt</code></td>
    </tr>
    <tr>
      <td>Virtual env</td>
      <td>Managed automatically</td>
      <td>Manual (<code class="language-plaintext highlighter-rouge">python -m venv</code>)</td>
    </tr>
    <tr>
      <td>Best for</td>
      <td>New projects, teams</td>
      <td>Legacy projects, simple scripts</td>
    </tr>
  </tbody>
</table>

<p>For new projects, start with <code class="language-plaintext highlighter-rouge">uv</code>. For existing projects using <code class="language-plaintext highlighter-rouge">requirements.txt</code>, <code class="language-plaintext highlighter-rouge">pip</code> works fine — no need to migrate unless you want to.</p>

<hr />

<h2 id="quick-reference">Quick reference</h2>

<table>
  <thead>
    <tr>
      <th>Task</th>
      <th><code class="language-plaintext highlighter-rouge">uv</code></th>
      <th><code class="language-plaintext highlighter-rouge">pip</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Create project</td>
      <td><code class="language-plaintext highlighter-rouge">uv init my-project</code></td>
      <td><code class="language-plaintext highlighter-rouge">mkdir my-project &amp;&amp; python -m venv .venv</code></td>
    </tr>
    <tr>
      <td>Add dependency</td>
      <td><code class="language-plaintext highlighter-rouge">uv add requests</code></td>
      <td><code class="language-plaintext highlighter-rouge">pip install requests</code></td>
    </tr>
    <tr>
      <td>Add dev dependency</td>
      <td><code class="language-plaintext highlighter-rouge">uv add pytest --dev</code></td>
      <td><code class="language-plaintext highlighter-rouge">pip install pytest</code></td>
    </tr>
    <tr>
      <td>Install from lockfile</td>
      <td><code class="language-plaintext highlighter-rouge">uv sync</code></td>
      <td><code class="language-plaintext highlighter-rouge">pip install -r requirements.txt</code></td>
    </tr>
    <tr>
      <td>Run a command</td>
      <td><code class="language-plaintext highlighter-rouge">uv run python main.py</code></td>
      <td><code class="language-plaintext highlighter-rouge">source .venv/bin/activate &amp;&amp; python main.py</code></td>
    </tr>
    <tr>
      <td>Run tests</td>
      <td><code class="language-plaintext highlighter-rouge">uv run pytest</code></td>
      <td><code class="language-plaintext highlighter-rouge">pytest</code> (inside activated venv)</td>
    </tr>
    <tr>
      <td>Run specific test</td>
      <td><code class="language-plaintext highlighter-rouge">uv run pytest tests/test_foo.py::test_bar</code></td>
      <td><code class="language-plaintext highlighter-rouge">pytest tests/test_foo.py::test_bar</code></td>
    </tr>
    <tr>
      <td>Verbose test output</td>
      <td><code class="language-plaintext highlighter-rouge">pytest -v</code></td>
      <td>same</td>
    </tr>
    <tr>
      <td>Stop on first failure</td>
      <td><code class="language-plaintext highlighter-rouge">pytest -x</code></td>
      <td>same</td>
    </tr>
  </tbody>
</table>]]></content><author><name>Seroze</name></author><category term="python" /><category term="python" /><category term="uv" /><category term="pip" /><category term="pytest" /><category term="project-setup" /><summary type="html"><![CDATA[Python has historically had too many ways to manage dependencies. This post covers the modern approach with uv, the pip fallback, and how to run tests with pytest.]]></summary></entry><entry><title type="html">Stripe Interview Preparation Guide</title><link href="/stripe-interview-prep/" rel="alternate" type="text/html" title="Stripe Interview Preparation Guide" /><published>2026-06-18T18:30:00+00:00</published><updated>2026-06-18T18:30:00+00:00</updated><id>/stripe-interview-prep</id><content type="html" xml:base="/stripe-interview-prep/"><![CDATA[<p><em>My preparation notes for the Stripe interview process. Using Python throughout and Zed as the editor.</em></p>

<blockquote>
  <p><strong>Disclaimer:</strong> The views and opinions expressed in this post are entirely my own and based on publicly available information. The problem statements included here were sourced from various online communities and discussion forums — they are not confirmed to be actual Stripe interview questions. This is a personal study guide, not an official representation of Stripe’s hiring process.</p>
</blockquote>

<hr />

<h2 id="the-process">The process</h2>

<p>Stripe’s interview loop typically has five stages:</p>

<ol>
  <li><strong>Online Assessment</strong> — timed coding problems on an external platform. Usually algorithmic, with a focus on correctness and edge cases.</li>
  <li><strong>Problem Solving</strong> — one or two technical interviews where you solve coding problems live with an engineer.</li>
  <li><strong>Bug Bash</strong> — you’re given a broken codebase and asked to find and fix bugs. Tests the ability to read unfamiliar code quickly.</li>
  <li><strong>Integration Round</strong> — design or extend a system, often involving APIs or working with existing abstractions. Less about algorithms, more about how you think about interfaces.</li>
  <li><strong>Hiring Manager Round</strong> — behavioural and motivation questions. Why Stripe, how you’ve worked in the past, how you handle ambiguity.</li>
</ol>

<hr />

<h2 id="setup">Setup</h2>

<p><strong>Language:</strong> Python 3<br />
<strong>Editor:</strong> Zed (<a href="/zed-editor/">setup guide</a>)</p>

<p>Disable auto-completion before every technical round — it won’t be available in most assessment environments and you don’t want to depend on it:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">//</span><span class="w"> </span><span class="err">Zed</span><span class="w"> </span><span class="err">settings</span><span class="w"> </span><span class="err">(Ctrl+,)</span><span class="w">
</span><span class="p">{</span><span class="w">
  </span><span class="nl">"show_completions_on_input"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<hr />

<h2 id="online-assessment">Online Assessment</h2>

<p><em>Problem statements and solutions to be added.</em></p>

<hr />

<h2 id="problem-solving">Problem Solving</h2>

<p><em>Problem statements and solutions to be added.</em></p>

<hr />

<h2 id="bug-bash">Bug Bash</h2>

<p>This round tests the scientific method in an unfamiliar codebase — not your ability to memorize APIs.</p>

<p><strong>What you’re given:</strong> a clone of a slightly modified internal project, a description of a reported failure, and a test suite where some tests are failing. Your job is to find and fix the bug.</p>

<h3 id="what-the-bugs-look-like">What the bugs look like</h3>

<p>They’re rarely algorithmic. Expect logic or configuration errors:</p>

<ul>
  <li><strong>Validation too strict</strong> — regex rejecting valid emails containing <code class="language-plaintext highlighter-rouge">+</code>, or a parser rejecting edge-case input it should accept</li>
  <li><strong>Platform assumptions</strong> — code that writes to a path without checking the directory exists first; works on the developer’s Mac, fails elsewhere</li>
  <li><strong>Logic gaps</strong> — a condition that misses a specific case, e.g. an <code class="language-plaintext highlighter-rouge">if</code> that handles <code class="language-plaintext highlighter-rouge">status == "active"</code> and <code class="language-plaintext highlighter-rouge">status == "inactive"</code> but silently drops <code class="language-plaintext highlighter-rouge">"pending"</code></li>
  <li><strong>Wrong library usage</strong> — passing arguments in the wrong order, using the wrong method variant, off-by-one in a range</li>
</ul>

<h3 id="debugging-methodology">Debugging methodology</h3>

<p>Randomly changing lines until tests pass will fail you. Follow a disciplined five-step process:</p>

<p><strong>1. Reproduction — confirm the failure first</strong></p>

<p>Run the failing tests immediately. Do not look at the code yet. Do not touch the code yet. You need a stable, confirmed failure before you can tell whether any change you make actually fixed anything. If you change code before reproducing, you lose your baseline.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pytest tests/ <span class="nt">-v</span>
<span class="c"># note exactly which tests fail and what the error message says</span>
</code></pre></div></div>

<p><strong>2. Isolation — read the stack trace, not the whole codebase</strong></p>

<p>Don’t start reading files top to bottom. Go straight to the stack trace. Find the exact line where the exception is raised or where the assertion fails. That’s your entry point into the code. Everything above it in the trace is call context — read upward only as needed.</p>

<p><strong>3. Hypothesis generation — say it out loud</strong></p>

<p>Form a specific, falsifiable statement before touching anything:</p>

<blockquote>
  <p>“I suspect the user ID is <code class="language-plaintext highlighter-rouge">None</code> here because the lookup is returning early”</p>
</blockquote>

<blockquote>
  <p>“I think this regex doesn’t account for <code class="language-plaintext highlighter-rouge">+</code> in the local part of the email”</p>
</blockquote>

<p>Vague suspicions (“something seems off here”) lead to random edits. A named hypothesis leads to a targeted test.</p>

<p><strong>4. Verification — add a print, confirm, then fix</strong></p>

<p>Add a <code class="language-plaintext highlighter-rouge">print</code> or <code class="language-plaintext highlighter-rouge">breakpoint()</code> just before the suspect line to confirm your hypothesis:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"DEBUG user_id=</span><span class="si">{</span><span class="n">user_id</span><span class="si">!r}</span><span class="s">"</span><span class="p">)</span>   <span class="c1"># is it None?
</span><span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"DEBUG pattern match: </span><span class="si">{</span><span class="n">re</span><span class="p">.</span><span class="n">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">,</span> <span class="n">email</span><span class="p">)</span><span class="si">!r}</span><span class="s">"</span><span class="p">)</span>
<span class="n">breakpoint</span><span class="p">()</span>   <span class="c1"># drop into pdb at runtime
</span></code></pre></div></div>

<p>Run only the failing test — not the whole suite — to iterate fast. Once confirmed, make the minimal fix.</p>

<p><strong>5. Cleanup — leave it cleaner than you found it</strong></p>

<p>Remove every <code class="language-plaintext highlighter-rouge">print</code> and <code class="language-plaintext highlighter-rouge">breakpoint()</code>. Run the full test suite. All previously passing tests must still pass. Commit with a clear message describing what was wrong and why.</p>

<h3 id="how-to-prepare">How to prepare</h3>

<p>The best practice is working with real bugs in real codebases:</p>

<ol>
  <li>
    <p>Go to the <a href="https://github.com/psf/requests">requests</a> or <a href="https://github.com/encode/httpx">httpx</a> GitHub repo. Filter issues by the <code class="language-plaintext highlighter-rouge">bug</code> label. Pick a closed one. Read the issue description, find the code that was broken, then read the PR that fixed it. Notice how small the fix usually is relative to the diagnosis work.</p>
  </li>
  <li>
    <p>Clone pandas or any library you know. Find a function, introduce a subtle break — change <code class="language-plaintext highlighter-rouge">&lt;</code> to <code class="language-plaintext highlighter-rouge">&lt;=</code>, swap two arguments, remove a <code class="language-plaintext highlighter-rouge">.strip()</code>. Then write a test that catches it and use the methodology above to find it. This builds the muscle memory of going from a failing test to a root cause without flailing.</p>
  </li>
</ol>

<hr />

<h2 id="api-fundamentals">API Fundamentals</h2>

<p>Stripe is a REST API company. The integration round and system design questions will expect you to be fluent in these basics.</p>

<h3 id="http-methods">HTTP Methods</h3>

<table>
  <thead>
    <tr>
      <th>Method</th>
      <th>Meaning</th>
      <th>Example</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">GET</code></td>
      <td>Read a resource, no side effects</td>
      <td><code class="language-plaintext highlighter-rouge">GET /customers/cus_123</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">POST</code></td>
      <td>Create a new resource</td>
      <td><code class="language-plaintext highlighter-rouge">POST /charges</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">PUT</code></td>
      <td>Replace a resource entirely</td>
      <td><code class="language-plaintext highlighter-rouge">PUT /customers/cus_123</code> (send all fields)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">PATCH</code></td>
      <td>Partially update a resource</td>
      <td><code class="language-plaintext highlighter-rouge">PATCH /customers/cus_123</code> (send only changed fields)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DELETE</code></td>
      <td>Remove a resource</td>
      <td><code class="language-plaintext highlighter-rouge">DELETE /customers/cus_123</code></td>
    </tr>
  </tbody>
</table>

<p>The distinction between <code class="language-plaintext highlighter-rouge">PUT</code> and <code class="language-plaintext highlighter-rouge">PATCH</code> matters: if you’re only updating a user’s status, use <code class="language-plaintext highlighter-rouge">PATCH</code> — <code class="language-plaintext highlighter-rouge">PUT</code> implies you’re replacing the whole object and anything you omit gets cleared.</p>

<hr />

<h3 id="http-status-codes">HTTP Status Codes</h3>

<p><strong>2xx — Success</strong></p>

<table>
  <thead>
    <tr>
      <th>Code</th>
      <th>Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">200 OK</code></td>
      <td>Standard success response</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">201 Created</code></td>
      <td>Resource was created (successful <code class="language-plaintext highlighter-rouge">POST</code>)</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">202 Accepted</code></td>
      <td>Request accepted but processing continues in the background (async jobs)</td>
    </tr>
  </tbody>
</table>

<p><strong>4xx — Client errors (you messed up)</strong></p>

<table>
  <thead>
    <tr>
      <th>Code</th>
      <th>Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">400 Bad Request</code></td>
      <td>Validation error, missing required field</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">401 Unauthorized</code></td>
      <td>Not authenticated — no API key or invalid key</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">403 Forbidden</code></td>
      <td>Authenticated but insufficient permissions</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">404 Not Found</code></td>
      <td>Resource doesn’t exist</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">429 Too Many Requests</code></td>
      <td>Rate limited — critical for Stripe integrations</td>
    </tr>
  </tbody>
</table>

<p>For <code class="language-plaintext highlighter-rouge">429</code>, you must know how to handle it: <strong>exponential backoff</strong>. Retry after 1s, then 2s, 4s, 8s — with jitter to avoid thundering herd. Don’t hammer the API on a tight loop.</p>

<p><strong>5xx — Server errors (Stripe messed up)</strong></p>

<table>
  <thead>
    <tr>
      <th>Code</th>
      <th>Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">500 Internal Server Error</code></td>
      <td>Unexpected error on the server</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">502 Bad Gateway</code></td>
      <td>Upstream service returned an invalid response</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">503 Service Unavailable</code></td>
      <td>Server down for maintenance or overloaded</td>
    </tr>
  </tbody>
</table>

<p>5xx errors are safe to retry (unlike 4xx which will keep failing). Same exponential backoff applies.</p>

<hr />

<h3 id="pagination-cursor-vs-offset">Pagination: Cursor vs Offset</h3>

<p><strong>Offset pagination</strong> (<code class="language-plaintext highlighter-rouge">?page=2&amp;limit=10</code>) is what most people reach for first. It’s inefficient and unstable:</p>

<ul>
  <li><strong>Inefficient:</strong> the database has to count and skip rows on every request — expensive at scale.</li>
  <li><strong>Unstable:</strong> if items are added or deleted while you’re paging, you’ll see duplicates or miss records.</li>
</ul>

<p><strong>Cursor pagination</strong> (<code class="language-plaintext highlighter-rouge">?starting_after=obj_id</code>) is what Stripe uses. The cursor points to a specific record in the database, and the query fetches the next N records after it. No counting, no skipping.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Stripe API example
</span><span class="n">page</span> <span class="o">=</span> <span class="n">stripe</span><span class="p">.</span><span class="n">Customer</span><span class="p">.</span><span class="nb">list</span><span class="p">(</span><span class="n">limit</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>

<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
    <span class="n">process</span><span class="p">(</span><span class="n">page</span><span class="p">.</span><span class="n">data</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">page</span><span class="p">.</span><span class="n">has_more</span><span class="p">:</span>
        <span class="k">break</span>
    <span class="n">page</span> <span class="o">=</span> <span class="n">stripe</span><span class="p">.</span><span class="n">Customer</span><span class="p">.</span><span class="nb">list</span><span class="p">(</span><span class="n">limit</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">starting_after</span><span class="o">=</span><span class="n">page</span><span class="p">.</span><span class="n">data</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">].</span><span class="nb">id</span><span class="p">)</span>
</code></pre></div></div>

<p>The response includes <code class="language-plaintext highlighter-rouge">has_more: true</code> if there are more records beyond the current page, <code class="language-plaintext highlighter-rouge">false</code> otherwise — clean and unambiguous. Cursor pagination is both efficient (index seek, no full scan) and stable (the cursor anchors to a fixed position in the dataset regardless of concurrent writes).</p>

<hr />

<h3 id="json-serialization-and-deserialization">JSON Serialization and Deserialization</h3>

<p>REST APIs speak JSON. You need to be comfortable converting between Python objects and JSON without reaching for documentation.</p>

<p><strong>Serialization — Python → JSON</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">json</span>

<span class="n">customer</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">"id"</span><span class="p">:</span> <span class="s">"cus_123"</span><span class="p">,</span>
    <span class="s">"name"</span><span class="p">:</span> <span class="s">"Alice"</span><span class="p">,</span>
    <span class="s">"email"</span><span class="p">:</span> <span class="s">"alice@example.com"</span><span class="p">,</span>
    <span class="s">"balance"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
    <span class="s">"metadata"</span><span class="p">:</span> <span class="p">{</span><span class="s">"plan"</span><span class="p">:</span> <span class="s">"pro"</span><span class="p">}</span>
<span class="p">}</span>

<span class="c1"># Python dict → JSON string
</span><span class="n">json_string</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">customer</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">json_string</span><span class="p">)</span>
<span class="c1"># '{"id": "cus_123", "name": "Alice", "email": "alice@example.com", ...}'
</span>
<span class="c1"># Pretty-print (useful for debugging)
</span><span class="k">print</span><span class="p">(</span><span class="n">json</span><span class="p">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">customer</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">2</span><span class="p">))</span>

<span class="c1"># Python dict → JSON file
</span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"customer.json"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">json</span><span class="p">.</span><span class="n">dump</span><span class="p">(</span><span class="n">customer</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">indent</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
</code></pre></div></div>

<p><strong>Deserialization — JSON → Python</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">json</span>

<span class="c1"># JSON string → Python dict
</span><span class="n">json_string</span> <span class="o">=</span> <span class="s">'{"id": "cus_123", "name": "Alice", "balance": 0}'</span>
<span class="n">customer</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">loads</span><span class="p">(</span><span class="n">json_string</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">customer</span><span class="p">[</span><span class="s">"name"</span><span class="p">])</span>   <span class="c1"># Alice
</span><span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">customer</span><span class="p">))</span>     <span class="c1"># &lt;class 'dict'&gt;
</span>
<span class="c1"># JSON file → Python dict
</span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"customer.json"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">customer</span> <span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</code></pre></div></div>

<p><strong>Serializing custom objects</strong></p>

<p><code class="language-plaintext highlighter-rouge">json.dumps</code> only handles built-in types (dict, list, str, int, float, bool, None). For custom classes you need a custom encoder or convert to dict first:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">json</span>
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span><span class="p">,</span> <span class="n">asdict</span>

<span class="o">@</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">Charge</span><span class="p">:</span>
    <span class="nb">id</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">amount</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">currency</span><span class="p">:</span> <span class="nb">str</span>

<span class="n">charge</span> <span class="o">=</span> <span class="n">Charge</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="s">"ch_123"</span><span class="p">,</span> <span class="n">amount</span><span class="o">=</span><span class="mi">2000</span><span class="p">,</span> <span class="n">currency</span><span class="o">=</span><span class="s">"usd"</span><span class="p">)</span>

<span class="c1"># Option 1: convert to dict manually
</span><span class="n">json</span><span class="p">.</span><span class="n">dumps</span><span class="p">({</span><span class="s">"id"</span><span class="p">:</span> <span class="n">charge</span><span class="p">.</span><span class="nb">id</span><span class="p">,</span> <span class="s">"amount"</span><span class="p">:</span> <span class="n">charge</span><span class="p">.</span><span class="n">amount</span><span class="p">,</span> <span class="s">"currency"</span><span class="p">:</span> <span class="n">charge</span><span class="p">.</span><span class="n">currency</span><span class="p">})</span>

<span class="c1"># Option 2: use asdict for dataclasses
</span><span class="n">json</span><span class="p">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">asdict</span><span class="p">(</span><span class="n">charge</span><span class="p">))</span>

<span class="c1"># Option 3: custom encoder
</span><span class="k">class</span> <span class="nc">ChargeEncoder</span><span class="p">(</span><span class="n">json</span><span class="p">.</span><span class="n">JSONEncoder</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">default</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">Charge</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">asdict</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
        <span class="k">return</span> <span class="nb">super</span><span class="p">().</span><span class="n">default</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>

<span class="n">json</span><span class="p">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">charge</span><span class="p">,</span> <span class="n">cls</span><span class="o">=</span><span class="n">ChargeEncoder</span><span class="p">)</span>
</code></pre></div></div>

<p><strong>Key distinction to remember:</strong></p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>String</th>
      <th>File</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Serialize</td>
      <td><code class="language-plaintext highlighter-rouge">json.dumps(obj)</code></td>
      <td><code class="language-plaintext highlighter-rouge">json.dump(obj, f)</code></td>
    </tr>
    <tr>
      <td>Deserialize</td>
      <td><code class="language-plaintext highlighter-rouge">json.loads(s)</code></td>
      <td><code class="language-plaintext highlighter-rouge">json.load(f)</code></td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">dumps</code>/<code class="language-plaintext highlighter-rouge">loads</code> — the <code class="language-plaintext highlighter-rouge">s</code> stands for string. <code class="language-plaintext highlighter-rouge">dump</code>/<code class="language-plaintext highlighter-rouge">load</code> — no <code class="language-plaintext highlighter-rouge">s</code>, takes a file handle.</p>

<hr />

<h3 id="reading-and-parsing-files-line-by-line">Reading and Parsing Files Line by Line</h3>

<p>Say you have a file with 100 lines, each containing a transaction: an integer ID, a float amount, and a float fee separated by commas:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1001,49.99,1.50
1002,120.00,3.60
1003,9.99,0.30
...
</code></pre></div></div>

<p><strong>Reading and parsing:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">transactions</span> <span class="o">=</span> <span class="p">[]</span>

<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"transactions.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">strip</span><span class="p">()</span>          <span class="c1"># remove trailing newline and whitespace
</span>        <span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">:</span>                 <span class="c1"># skip empty lines
</span>            <span class="k">continue</span>
        <span class="n">parts</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">","</span><span class="p">)</span>
        <span class="n">txn_id</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
        <span class="n">amount</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">parts</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="n">fee</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">parts</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
        <span class="n">transactions</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="n">txn_id</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">fee</span><span class="p">))</span>

<span class="c1"># or more concisely with unpacking
</span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"transactions.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">strip</span><span class="p">()</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">:</span>
            <span class="k">continue</span>
        <span class="n">txn_id</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">fee</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">","</span><span class="p">)</span>
        <span class="n">transactions</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="nb">int</span><span class="p">(</span><span class="n">txn_id</span><span class="p">),</span> <span class="nb">float</span><span class="p">(</span><span class="n">amount</span><span class="p">),</span> <span class="nb">float</span><span class="p">(</span><span class="n">fee</span><span class="p">)))</span>
</code></pre></div></div>

<p><strong>Processing — total revenue, total fees:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">total_amount</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">transactions</span><span class="p">)</span>
<span class="n">total_fees</span>   <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">transactions</span><span class="p">)</span>
<span class="n">net</span>          <span class="o">=</span> <span class="n">total_amount</span> <span class="o">-</span> <span class="n">total_fees</span>

<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Transactions: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">transactions</span><span class="p">)</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Total amount: </span><span class="si">{</span><span class="n">total_amount</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Total fees:   </span><span class="si">{</span><span class="n">total_fees</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"Net revenue:  </span><span class="si">{</span><span class="n">net</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>

<p><strong>Things to always do:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">strip()</code> every line — trailing <code class="language-plaintext highlighter-rouge">\n</code> will break <code class="language-plaintext highlighter-rouge">int()</code>/<code class="language-plaintext highlighter-rouge">float()</code> silently turning into a <code class="language-plaintext highlighter-rouge">ValueError</code></li>
  <li>Guard against empty lines — files often have a trailing newline that produces a blank last line</li>
  <li>Use <code class="language-plaintext highlighter-rouge">with open(...)</code> — it closes the file automatically even if an exception is raised</li>
</ul>

<p><strong>Does <code class="language-plaintext highlighter-rouge">for line in f</code> load the whole file into memory?</strong></p>

<p>No — iterating over a file object in Python is lazy. It reads one line at a time using the OS’s buffered I/O (typically 8KB chunks internally), but exposes it to you one line at a time. The whole file is never in memory at once. This is safe and efficient even for multi-GB files.</p>

<p>The things that <em>do</em> load the whole file into memory: <code class="language-plaintext highlighter-rouge">f.read()</code> (one giant string) and <code class="language-plaintext highlighter-rouge">f.readlines()</code> (list of all lines). Avoid these for large files — use the <code class="language-plaintext highlighter-rouge">for line in f</code> loop instead.</p>

<p><strong>Writing to a file:</strong></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">transactions</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="mi">1001</span><span class="p">,</span> <span class="mf">49.99</span><span class="p">,</span> <span class="mf">1.50</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">1002</span><span class="p">,</span> <span class="mf">120.00</span><span class="p">,</span> <span class="mf">3.60</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">1003</span><span class="p">,</span> <span class="mf">9.99</span><span class="p">,</span> <span class="mf">0.30</span><span class="p">),</span>
<span class="p">]</span>

<span class="c1"># Write (overwrites if file exists)
</span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"output.txt"</span><span class="p">,</span> <span class="s">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">txn_id</span><span class="p">,</span> <span class="n">amount</span><span class="p">,</span> <span class="n">fee</span> <span class="ow">in</span> <span class="n">transactions</span><span class="p">:</span>
        <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">txn_id</span><span class="si">}</span><span class="s">,</span><span class="si">{</span><span class="n">amount</span><span class="si">}</span><span class="s">,</span><span class="si">{</span><span class="n">fee</span><span class="si">}</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

<span class="c1"># Append (adds to end of file without overwriting)
</span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"output.txt"</span><span class="p">,</span> <span class="s">"a"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
    <span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="mi">1004</span><span class="si">}</span><span class="s">,</span><span class="si">{</span><span class="mf">75.00</span><span class="si">}</span><span class="s">,</span><span class="si">{</span><span class="mf">2.25</span><span class="si">}</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
</code></pre></div></div>

<p>File modes:</p>

<table>
  <thead>
    <tr>
      <th>Mode</th>
      <th>Behaviour</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">"r"</code></td>
      <td>Read (default) — error if file doesn’t exist</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">"w"</code></td>
      <td>Write — creates file if missing, <strong>truncates if it exists</strong></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">"a"</code></td>
      <td>Append — creates file if missing, preserves existing content</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">"r+"</code></td>
      <td>Read and write — file must exist</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="integration-round">Integration Round</h2>

<p>This round is less about algorithms and more about how you think through interfaces, data structures, and system design at the code level. You’ll be asked to build something real — not pseudocode.</p>

<p><strong>Language note:</strong> Prefer Python over Java here. Less boilerplate means more time thinking about the actual problem. That said, Python’s dynamic typing is a double-edged sword — a typo in a variable name won’t be caught at compile time and will silently blow up at runtime. Be deliberate: name variables clearly, re-read your code before running, and test incrementally.</p>

<hr />

<h3 id="question-bank">Question bank</h3>

<p><strong>Webhook delivery system</strong>
Design an architecture for delivering webhook notifications to customers when a payment event occurs. The system must send HTTP requests with event payloads to all predefined merchant URLs. Requirements: payment events must never be lost, third-party endpoint failures must be retried, and merchants need a dashboard to view the history of all webhook attempts.</p>

<p>Core architecture:</p>
<ul>
  <li>When a payment occurs, persist the event to a durable queue (e.g. a <code class="language-plaintext highlighter-rouge">webhook_events</code> DB table or message queue) <em>before</em> attempting delivery — this is what guarantees no event is lost.</li>
  <li>A worker pool picks up pending events and POSTs to each registered endpoint. On failure (non-2xx or timeout), write the attempt to a <code class="language-plaintext highlighter-rouge">webhook_attempts</code> log and re-enqueue with exponential backoff.</li>
  <li>Each attempt (timestamp, status code, response body, latency) is stored so the dashboard can show the full delivery history per event.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Payment Service → [webhook_events table] → Delivery Workers → Merchant URL
                                                ↓
                                       [webhook_attempts log] → Dashboard API
</code></pre></div></div>

<p>Retry policy: back off exponentially (1s, 2s, 4s, 8s…) up to a max (e.g. 72 hours), then mark the event as permanently failed and alert the merchant.</p>

<p><strong>Follow-up 1: How would you add rate limiting?</strong>
Use a sliding window per merchant — cap outgoing webhook requests to N per minute. Before dispatching a delivery, check the counter. If the merchant is at the limit, delay the attempt (reschedule it rather than dropping it). See the rate limiter question below.</p>

<p><strong>Follow-up 2: Some merchants receive huge volumes while others receive very few. How do you ensure small merchants aren’t starved?</strong>
A single global queue lets a high-volume merchant monopolise the workers. Instead, use <strong>per-merchant queues</strong> with round-robin dispatch across merchants. Each worker iteration picks one event from merchant A, one from merchant B, one from merchant C — regardless of how full each queue is. High-volume merchants get proportionally more throughput as queue depth grows, but they can never block small merchants entirely.</p>

<p><strong>Real-time payment system with idempotency</strong>
How would you design a real-time payment system that prevents duplicate charges? Key concept: idempotency keys. A client sends a unique key with each request; the server stores the result against that key and returns the cached result on retries rather than processing the charge again. Design the data model, the key storage, and the expiry policy.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">hashlib</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span><span class="p">,</span> <span class="n">field</span>
<span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>

<span class="k">class</span> <span class="nc">PaymentStatus</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
    <span class="n">PENDING</span>   <span class="o">=</span> <span class="s">"pending"</span>
    <span class="n">SUCCEEDED</span> <span class="o">=</span> <span class="s">"succeeded"</span>
    <span class="n">FAILED</span>    <span class="o">=</span> <span class="s">"failed"</span>

<span class="o">@</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">PaymentResult</span><span class="p">:</span>
    <span class="n">status</span><span class="p">:</span> <span class="n">PaymentStatus</span>
    <span class="n">charge_id</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">amount</span><span class="p">:</span> <span class="nb">int</span>
    <span class="n">currency</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">created_at</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">default_factory</span><span class="o">=</span><span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">PaymentProcessor</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ttl_seconds</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">86400</span><span class="p">):</span>  <span class="c1"># keys expire after 24h
</span>        <span class="bp">self</span><span class="p">.</span><span class="n">_idempotency_store</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">PaymentResult</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_ttl</span> <span class="o">=</span> <span class="n">ttl_seconds</span>

    <span class="k">def</span> <span class="nf">charge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">idempotency_key</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">amount</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">currency</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">PaymentResult</span><span class="p">:</span>
        <span class="c1"># return cached result if this key was seen before
</span>        <span class="k">if</span> <span class="n">idempotency_key</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">_idempotency_store</span><span class="p">:</span>
            <span class="n">cached</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">_idempotency_store</span><span class="p">[</span><span class="n">idempotency_key</span><span class="p">]</span>
            <span class="k">if</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">cached</span><span class="p">.</span><span class="n">created_at</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="p">.</span><span class="n">_ttl</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">cached</span>
            <span class="c1"># expired — remove and reprocess
</span>            <span class="k">del</span> <span class="bp">self</span><span class="p">.</span><span class="n">_idempotency_store</span><span class="p">[</span><span class="n">idempotency_key</span><span class="p">]</span>

        <span class="n">result</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">_process_charge</span><span class="p">(</span><span class="n">amount</span><span class="p">,</span> <span class="n">currency</span><span class="p">)</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_idempotency_store</span><span class="p">[</span><span class="n">idempotency_key</span><span class="p">]</span> <span class="o">=</span> <span class="n">result</span>
        <span class="k">return</span> <span class="n">result</span>

    <span class="k">def</span> <span class="nf">_process_charge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">amount</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">currency</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">PaymentResult</span><span class="p">:</span>
        <span class="c1"># in reality: call card network, write to DB, etc.
</span>        <span class="n">charge_id</span> <span class="o">=</span> <span class="n">hashlib</span><span class="p">.</span><span class="n">sha256</span><span class="p">(</span><span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">amount</span><span class="si">}{</span><span class="n">currency</span><span class="si">}{</span><span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span><span class="si">}</span><span class="s">"</span><span class="p">.</span><span class="n">encode</span><span class="p">()).</span><span class="n">hexdigest</span><span class="p">()[:</span><span class="mi">16</span><span class="p">]</span>
        <span class="k">return</span> <span class="n">PaymentResult</span><span class="p">(</span>
            <span class="n">status</span><span class="o">=</span><span class="n">PaymentStatus</span><span class="p">.</span><span class="n">SUCCEEDED</span><span class="p">,</span>
            <span class="n">charge_id</span><span class="o">=</span><span class="n">charge_id</span><span class="p">,</span>
            <span class="n">amount</span><span class="o">=</span><span class="n">amount</span><span class="p">,</span>
            <span class="n">currency</span><span class="o">=</span><span class="n">currency</span><span class="p">,</span>
        <span class="p">)</span>
</code></pre></div></div>

<p>Key points:</p>
<ul>
  <li>Check the store <em>before</em> processing — return the cached <code class="language-plaintext highlighter-rouge">PaymentResult</code> immediately on a duplicate key. The charge logic never runs twice.</li>
  <li>The idempotency key is supplied by the <em>client</em> (e.g. a UUID they generate before the first attempt). The server never generates it.</li>
  <li>TTL prevents the store from growing unboundedly. 24 hours is Stripe’s policy.</li>
  <li>In production, the store is a database table (not an in-process dict) so it survives restarts and works across multiple server instances. The key column has a <code class="language-plaintext highlighter-rouge">UNIQUE</code> constraint — a race between two simultaneous requests with the same key is resolved by the DB rejecting one insert.</li>
</ul>

<p><strong>Currency exchange algorithm</strong>
Design an algorithm that converts an amount from one currency to another given a table of exchange rates. Extension: what if a direct rate doesn’t exist and you need to chain conversions (USD → EUR → GBP)?</p>

<p><strong>Parse currency/shipping rate string</strong>
Parse a string in this format:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>USD:CAD:DHL:5, USD:GBP:FedEx:3, EUR:USD:UPS:8
</code></pre></div></div>
<p>Each entry represents: <code class="language-plaintext highlighter-rouge">source_currency:target_currency:carrier:rate</code>. Write a method that takes a source currency, target currency, and amount, and returns the converted amount and the carrier to use.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">parse_rates</span><span class="p">(</span><span class="n">rate_string</span><span class="p">):</span>
    <span class="n">rates</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">rate_string</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">", "</span><span class="p">):</span>
        <span class="n">src</span><span class="p">,</span> <span class="n">tgt</span><span class="p">,</span> <span class="n">carrier</span><span class="p">,</span> <span class="n">rate</span> <span class="o">=</span> <span class="n">entry</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">":"</span><span class="p">)</span>
        <span class="n">rates</span><span class="p">[(</span><span class="n">src</span><span class="p">,</span> <span class="n">tgt</span><span class="p">)]</span> <span class="o">=</span> <span class="p">(</span><span class="n">carrier</span><span class="p">,</span> <span class="nb">float</span><span class="p">(</span><span class="n">rate</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">rates</span>

<span class="k">def</span> <span class="nf">convert</span><span class="p">(</span><span class="n">rates</span><span class="p">,</span> <span class="n">src</span><span class="p">,</span> <span class="n">tgt</span><span class="p">,</span> <span class="n">amount</span><span class="p">):</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">tgt</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">rates</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nb">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s">"No rate for </span><span class="si">{</span><span class="n">src</span><span class="si">}</span><span class="s"> -&gt; </span><span class="si">{</span><span class="n">tgt</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
    <span class="n">carrier</span><span class="p">,</span> <span class="n">rate</span> <span class="o">=</span> <span class="n">rates</span><span class="p">[(</span><span class="n">src</span><span class="p">,</span> <span class="n">tgt</span><span class="p">)]</span>
    <span class="k">return</span> <span class="n">amount</span> <span class="o">*</span> <span class="n">rate</span><span class="p">,</span> <span class="n">carrier</span>
</code></pre></div></div>

<p><strong>Invoice scheduler</strong>
Design a system for scheduling invoices to be sent at a future time. Think about: the data model for a scheduled job, how you’d persist and poll pending invoices, handling clock skew, and what happens if the scheduler crashes mid-send.</p>

<p><strong>CSV processing and validation</strong>
Given a CSV file of transactions, parse and validate the data. Common validation rules: required fields present, numeric fields are valid numbers, dates are in the expected format, no duplicate IDs. Return a list of valid rows and a list of errors with line numbers.</p>

<p><strong>Shipping cost calculator</strong>
Given a list of orders each with an associated country, calculate the shipping cost for each order. The rate table maps country → cost. Handle missing countries, bulk discounts, and free shipping thresholds.</p>

<p><strong>Server load balancer</strong>
Build the data structures and logic to manage a pool of servers and distribute client connections across them. Operations to implement:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">connect(client_id)</code> — assign a client to a server using the balancing strategy</li>
  <li><code class="language-plaintext highlighter-rouge">disconnect(client_id)</code> — release a client’s connection</li>
  <li><code class="language-plaintext highlighter-rouge">shutdown(server_id)</code> — graceful shutdown: migrate all existing connections from this server to others, then remove it from the pool</li>
</ul>

<p>Balancing strategies to know:</p>
<ul>
  <li><strong>Round robin</strong> — cycle through servers in order; simple, assumes homogeneous servers</li>
  <li><strong>Least connections</strong> — assign to the server with the fewest active connections; better for variable-length sessions</li>
  <li><strong>Consistent hashing</strong> — hash the client ID to a point on a ring; each server owns a range; adding/removing a server only remaps a fraction of clients — important for stateful sessions</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>

<span class="k">class</span> <span class="nc">LoadBalancer</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">servers</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">servers</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">servers</span><span class="p">)</span>        <span class="c1"># available server IDs
</span>        <span class="bp">self</span><span class="p">.</span><span class="n">connections</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">set</span><span class="p">)</span> <span class="c1"># server_id -&gt; set of client_ids
</span>        <span class="bp">self</span><span class="p">.</span><span class="n">client_map</span> <span class="o">=</span> <span class="p">{}</span>                <span class="c1"># client_id -&gt; server_id
</span>        <span class="bp">self</span><span class="p">.</span><span class="n">_rr_index</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">client_id</span><span class="p">):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="p">.</span><span class="n">servers</span><span class="p">:</span>
            <span class="k">raise</span> <span class="nb">RuntimeError</span><span class="p">(</span><span class="s">"No servers available"</span><span class="p">)</span>
        <span class="n">server</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">servers</span><span class="p">[</span><span class="bp">self</span><span class="p">.</span><span class="n">_rr_index</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">servers</span><span class="p">)]</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_rr_index</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">connections</span><span class="p">[</span><span class="n">server</span><span class="p">].</span><span class="n">add</span><span class="p">(</span><span class="n">client_id</span><span class="p">)</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">client_map</span><span class="p">[</span><span class="n">client_id</span><span class="p">]</span> <span class="o">=</span> <span class="n">server</span>
        <span class="k">return</span> <span class="n">server</span>

    <span class="k">def</span> <span class="nf">disconnect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">client_id</span><span class="p">):</span>
        <span class="n">server</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">client_map</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="n">client_id</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">server</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">connections</span><span class="p">[</span><span class="n">server</span><span class="p">].</span><span class="n">discard</span><span class="p">(</span><span class="n">client_id</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">shutdown</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server_id</span><span class="p">):</span>
        <span class="c1"># remove from rotation first so connect() won't pick it
</span>        <span class="bp">self</span><span class="p">.</span><span class="n">servers</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">server_id</span><span class="p">)</span>
        <span class="c1"># migrate every existing client to a new server
</span>        <span class="k">for</span> <span class="n">client_id</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">connections</span><span class="p">[</span><span class="n">server_id</span><span class="p">]):</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">disconnect</span><span class="p">(</span><span class="n">client_id</span><span class="p">)</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">client_id</span><span class="p">)</span>
        <span class="k">del</span> <span class="bp">self</span><span class="p">.</span><span class="n">connections</span><span class="p">[</span><span class="n">server_id</span><span class="p">]</span>

    <span class="k">def</span> <span class="nf">least_connections_connect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">client_id</span><span class="p">):</span>
        <span class="n">server</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">servers</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">connections</span><span class="p">[</span><span class="n">s</span><span class="p">]))</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">connections</span><span class="p">[</span><span class="n">server</span><span class="p">].</span><span class="n">add</span><span class="p">(</span><span class="n">client_id</span><span class="p">)</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">client_map</span><span class="p">[</span><span class="n">client_id</span><span class="p">]</span> <span class="o">=</span> <span class="n">server</span>
        <span class="k">return</span> <span class="n">server</span>
</code></pre></div></div>

<p>Key points for the interview:</p>
<ul>
  <li>Remove the server from <code class="language-plaintext highlighter-rouge">self.servers</code> <em>before</em> migrating connections so that <code class="language-plaintext highlighter-rouge">connect()</code> during migration doesn’t route back to the shutting-down server.</li>
  <li><code class="language-plaintext highlighter-rouge">list(self.connections[server_id])</code> — copy the set before iterating because <code class="language-plaintext highlighter-rouge">disconnect</code> mutates it.</li>
  <li>Least-connections just needs <code class="language-plaintext highlighter-rouge">min(..., key=lambda s: len(self.connections[s]))</code> — one line once the data structure is in place.</li>
</ul>

<p><strong>Invoice reminder email subjects</strong>
Your invoicing system needs a configurable reminder schedule. Given an invoice and a schedule of day offsets relative to the due date, output the subject line of every email that would be sent, in sorted (chronological) order.</p>

<p>Example schedule: send an email 10 days before the due date, on the due date, 20 days after, and 30 days after.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">date</span><span class="p">,</span> <span class="n">timedelta</span>

<span class="n">SCHEDULE</span> <span class="o">=</span> <span class="p">[</span>
    <span class="p">(</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="s">"Reminder: Invoice #{id} is due in 10 days"</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">0</span><span class="p">,</span>   <span class="s">"Invoice #{id} is due today"</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">20</span><span class="p">,</span>  <span class="s">"Invoice #{id} is 20 days overdue — please pay"</span><span class="p">),</span>
    <span class="p">(</span><span class="mi">30</span><span class="p">,</span>  <span class="s">"Final notice: Invoice #{id} is 30 days overdue"</span><span class="p">),</span>
<span class="p">]</span>

<span class="k">def</span> <span class="nf">email_subjects</span><span class="p">(</span><span class="n">invoice_id</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">due_date</span><span class="p">:</span> <span class="n">date</span><span class="p">,</span> <span class="n">schedule</span><span class="o">=</span><span class="n">SCHEDULE</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
    <span class="n">emails</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">offset</span><span class="p">,</span> <span class="n">template</span> <span class="ow">in</span> <span class="n">schedule</span><span class="p">:</span>
        <span class="n">send_date</span> <span class="o">=</span> <span class="n">due_date</span> <span class="o">+</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="n">offset</span><span class="p">)</span>
        <span class="n">subject</span> <span class="o">=</span> <span class="n">template</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="n">invoice_id</span><span class="p">)</span>
        <span class="n">emails</span><span class="p">.</span><span class="n">append</span><span class="p">((</span><span class="n">send_date</span><span class="p">,</span> <span class="n">subject</span><span class="p">))</span>

    <span class="n">emails</span><span class="p">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>        <span class="c1"># sort chronologically
</span>    <span class="k">return</span> <span class="p">[</span><span class="n">subject</span> <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">subject</span> <span class="ow">in</span> <span class="n">emails</span><span class="p">]</span>

<span class="c1"># Example
</span><span class="n">subjects</span> <span class="o">=</span> <span class="n">email_subjects</span><span class="p">(</span><span class="s">"INV-001"</span><span class="p">,</span> <span class="n">date</span><span class="p">(</span><span class="mi">2024</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">15</span><span class="p">))</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">subjects</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="c1"># Reminder: Invoice #INV-001 is due in 10 days
# Invoice #INV-001 is due today
# Invoice #INV-001 is 20 days overdue — please pay
# Final notice: Invoice #INV-001 is 30 days overdue
</span></code></pre></div></div>

<p>The schedule is just a list of <code class="language-plaintext highlighter-rouge">(offset, template)</code> tuples — fully configurable, no special-casing. Sorting on <code class="language-plaintext highlighter-rouge">send_date</code> (a <code class="language-plaintext highlighter-rouge">date</code> object) is naturally chronological. The subject template uses <code class="language-plaintext highlighter-rouge">.format(id=...)</code> so the invoice ID is injected without hardcoding.</p>

<p><strong>Word Search (LeetCode)</strong>
Given a 2D board of characters and a word, return true if the word exists in the grid following adjacent cells (horizontal/vertical, no reuse). Classic DFS with backtracking — mark a cell visited before recursing, unmark on the way back out.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">exist</span><span class="p">(</span><span class="n">board</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]],</span> <span class="n">word</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
    <span class="n">rows</span><span class="p">,</span> <span class="n">cols</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">board</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">board</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>

    <span class="k">def</span> <span class="nf">dfs</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">):</span>
            <span class="k">return</span> <span class="bp">True</span>
        <span class="k">if</span> <span class="n">r</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">r</span> <span class="o">&gt;=</span> <span class="n">rows</span> <span class="ow">or</span> <span class="n">c</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">c</span> <span class="o">&gt;=</span> <span class="n">cols</span> <span class="ow">or</span> <span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">!=</span> <span class="n">word</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
            <span class="k">return</span> <span class="bp">False</span>
        <span class="n">tmp</span><span class="p">,</span> <span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">],</span> <span class="s">"#"</span>    <span class="c1"># mark visited in-place
</span>        <span class="n">found</span> <span class="o">=</span> <span class="p">(</span><span class="n">dfs</span><span class="p">(</span><span class="n">r</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="ow">or</span>
                 <span class="n">dfs</span><span class="p">(</span><span class="n">r</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="ow">or</span>
                 <span class="n">dfs</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span> <span class="ow">or</span>
                 <span class="n">dfs</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
        <span class="n">board</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span>                       <span class="c1"># restore on the way back out
</span>        <span class="k">return</span> <span class="n">found</span>

    <span class="k">return</span> <span class="nb">any</span><span class="p">(</span><span class="n">dfs</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">rows</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">cols</span><span class="p">))</span>
</code></pre></div></div>

<p>Key points:</p>
<ul>
  <li>Temporarily overwrite the cell with <code class="language-plaintext highlighter-rouge">"#"</code> to mark it visited — no separate <code class="language-plaintext highlighter-rouge">visited</code> set needed.</li>
  <li>Restore the cell after the recursive call returns (backtracking). Without this, the mutation from one DFS path would corrupt subsequent paths.</li>
  <li>The base case <code class="language-plaintext highlighter-rouge">i == len(word)</code> fires when every character has been matched — return <code class="language-plaintext highlighter-rouge">True</code> immediately.</li>
  <li>Short-circuit with <code class="language-plaintext highlighter-rouge">or</code> — as soon as one direction succeeds, stop exploring.</li>
</ul>

<p><strong>Rate limiter (100 requests per minute per user)</strong>
Design a rate limiter that allows each unique user at most 100 requests per minute. The classic approach is a <strong>sliding window</strong> — track the timestamps of recent requests and evict ones outside the window.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">deque</span>

<span class="k">class</span> <span class="nc">RateLimiter</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">max_requests</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">100</span><span class="p">,</span> <span class="n">window_seconds</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">60</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">max_requests</span> <span class="o">=</span> <span class="n">max_requests</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">window</span> <span class="o">=</span> <span class="n">window_seconds</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">user_windows</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">deque</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">def</span> <span class="nf">is_allowed</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user_id</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
        <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">user_id</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">user_windows</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">user_windows</span><span class="p">[</span><span class="n">user_id</span><span class="p">]</span> <span class="o">=</span> <span class="n">deque</span><span class="p">()</span>

        <span class="n">window</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">user_windows</span><span class="p">[</span><span class="n">user_id</span><span class="p">]</span>
        <span class="c1"># evict timestamps that have fallen outside the window
</span>        <span class="k">while</span> <span class="n">window</span> <span class="ow">and</span> <span class="n">window</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="n">now</span> <span class="o">-</span> <span class="bp">self</span><span class="p">.</span><span class="n">window</span><span class="p">:</span>
            <span class="n">window</span><span class="p">.</span><span class="n">popleft</span><span class="p">()</span>

        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">window</span><span class="p">)</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="p">.</span><span class="n">max_requests</span><span class="p">:</span>
            <span class="n">window</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">now</span><span class="p">)</span>
            <span class="k">return</span> <span class="bp">True</span>
        <span class="k">return</span> <span class="bp">False</span>   <span class="c1"># rate limited — caller should return 429
</span></code></pre></div></div>

<p>Key points:</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">deque</code> with <code class="language-plaintext highlighter-rouge">popleft()</code> is O(1) for eviction vs a list which is O(n).</li>
  <li>Evict <em>before</em> checking the count — otherwise stale timestamps inflate the count.</li>
  <li>At scale, replace the in-process dict with Redis (use a sorted set keyed by <code class="language-plaintext highlighter-rouge">user_id</code>, scored by timestamp). This makes it work across multiple server instances.</li>
  <li>Trade-off: sliding window is accurate but uses O(requests) memory per user. Fixed window (just a counter + reset time) uses O(1) but allows bursts at window boundaries.</li>
</ul>

<hr />

<p><strong>Document signing system (Docusign-like)</strong>
Design the architecture for a system where a sender uploads a document, specifies signatories, and each signatory receives a link to sign. The document is considered complete when all parties have signed.</p>

<p>Core components:</p>
<ul>
  <li><strong>Document store</strong> — store the original PDF in object storage (S3). Never mutate the original; each signature creates a new version.</li>
  <li><strong>Signing workflow state machine</strong> — track state per document: <code class="language-plaintext highlighter-rouge">draft → sent → partially_signed → completed | expired | voided</code>. Each signatory has their own <code class="language-plaintext highlighter-rouge">pending → signed | declined</code> state.</li>
  <li><strong>Audit trail</strong> — every event (sent, viewed, signed, declined) is appended to an immutable log with timestamp and IP.</li>
  <li><strong>Notification service</strong> — email each signatory when it’s their turn. Email the sender when all parties have signed.</li>
  <li><strong>Signed document generation</strong> — once all signatures are collected, render the final PDF with signature blocks embedded and store it separately.</li>
</ul>

<p>Follow-up questions to be ready for: how do you prevent someone from signing twice? (idempotency token in the signing URL) How do you handle a signatory declining? (notify sender, allow resend or void) What if the document expires? (cron job scans for past-deadline <code class="language-plaintext highlighter-rouge">sent</code> documents and transitions them to <code class="language-plaintext highlighter-rouge">expired</code>).</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">uuid</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">from</span> <span class="nn">dataclasses</span> <span class="kn">import</span> <span class="n">dataclass</span><span class="p">,</span> <span class="n">field</span>
<span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>

<span class="k">class</span> <span class="nc">DocStatus</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
    <span class="n">DRAFT</span>            <span class="o">=</span> <span class="s">"draft"</span>
    <span class="n">SENT</span>             <span class="o">=</span> <span class="s">"sent"</span>
    <span class="n">PARTIALLY_SIGNED</span> <span class="o">=</span> <span class="s">"partially_signed"</span>
    <span class="n">COMPLETED</span>        <span class="o">=</span> <span class="s">"completed"</span>
    <span class="n">EXPIRED</span>          <span class="o">=</span> <span class="s">"expired"</span>
    <span class="n">VOIDED</span>           <span class="o">=</span> <span class="s">"voided"</span>

<span class="k">class</span> <span class="nc">SignatoryStatus</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
    <span class="n">PENDING</span>  <span class="o">=</span> <span class="s">"pending"</span>
    <span class="n">SIGNED</span>   <span class="o">=</span> <span class="s">"signed"</span>
    <span class="n">DECLINED</span> <span class="o">=</span> <span class="s">"declined"</span>

<span class="o">@</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">Signatory</span><span class="p">:</span>
    <span class="n">email</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">token</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">default_factory</span><span class="o">=</span><span class="k">lambda</span><span class="p">:</span> <span class="n">uuid</span><span class="p">.</span><span class="n">uuid4</span><span class="p">().</span><span class="nb">hex</span><span class="p">)</span>  <span class="c1"># unique signing URL token
</span>    <span class="n">status</span><span class="p">:</span> <span class="n">SignatoryStatus</span> <span class="o">=</span> <span class="n">SignatoryStatus</span><span class="p">.</span><span class="n">PENDING</span>
    <span class="n">signed_at</span><span class="p">:</span> <span class="nb">float</span> <span class="o">|</span> <span class="bp">None</span> <span class="o">=</span> <span class="bp">None</span>

<span class="o">@</span><span class="n">dataclass</span>
<span class="k">class</span> <span class="nc">Document</span><span class="p">:</span>
    <span class="n">doc_id</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">owner_email</span><span class="p">:</span> <span class="nb">str</span>
    <span class="n">signatories</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Signatory</span><span class="p">]</span>
    <span class="n">status</span><span class="p">:</span> <span class="n">DocStatus</span> <span class="o">=</span> <span class="n">DocStatus</span><span class="p">.</span><span class="n">DRAFT</span>
    <span class="n">expires_at</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">default_factory</span><span class="o">=</span><span class="k">lambda</span><span class="p">:</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span> <span class="o">+</span> <span class="mi">7</span> <span class="o">*</span> <span class="mi">86400</span><span class="p">)</span>  <span class="c1"># 7 days
</span>    <span class="n">audit_log</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">dict</span><span class="p">]</span> <span class="o">=</span> <span class="n">field</span><span class="p">(</span><span class="n">default_factory</span><span class="o">=</span><span class="nb">list</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">_log</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">actor</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">audit_log</span><span class="p">.</span><span class="n">append</span><span class="p">({</span><span class="s">"event"</span><span class="p">:</span> <span class="n">event</span><span class="p">,</span> <span class="s">"actor"</span><span class="p">:</span> <span class="n">actor</span><span class="p">,</span> <span class="s">"ts"</span><span class="p">:</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">(),</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">})</span>

    <span class="k">def</span> <span class="nf">send</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">DocStatus</span><span class="p">.</span><span class="n">SENT</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_log</span><span class="p">(</span><span class="s">"sent"</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">owner_email</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">signatories</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">_notify</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">email</span><span class="p">,</span> <span class="sa">f</span><span class="s">"Please sign: /sign/</span><span class="si">{</span><span class="n">s</span><span class="p">.</span><span class="n">token</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">sign</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="p">.</span><span class="n">expires_at</span><span class="p">:</span>
            <span class="k">return</span> <span class="s">"expired"</span>

        <span class="n">signatory</span> <span class="o">=</span> <span class="nb">next</span><span class="p">((</span><span class="n">s</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">signatories</span> <span class="k">if</span> <span class="n">s</span><span class="p">.</span><span class="n">token</span> <span class="o">==</span> <span class="n">token</span><span class="p">),</span> <span class="bp">None</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">signatory</span><span class="p">:</span>
            <span class="k">return</span> <span class="s">"invalid_token"</span>
        <span class="k">if</span> <span class="n">signatory</span><span class="p">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">SignatoryStatus</span><span class="p">.</span><span class="n">SIGNED</span><span class="p">:</span>
            <span class="k">return</span> <span class="s">"already_signed"</span>   <span class="c1"># idempotent — no double processing
</span>
        <span class="n">signatory</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">SignatoryStatus</span><span class="p">.</span><span class="n">SIGNED</span>
        <span class="n">signatory</span><span class="p">.</span><span class="n">signed_at</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_log</span><span class="p">(</span><span class="s">"signed"</span><span class="p">,</span> <span class="n">signatory</span><span class="p">.</span><span class="n">email</span><span class="p">)</span>

        <span class="k">if</span> <span class="nb">all</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">SignatoryStatus</span><span class="p">.</span><span class="n">SIGNED</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">signatories</span><span class="p">):</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">DocStatus</span><span class="p">.</span><span class="n">COMPLETED</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">_log</span><span class="p">(</span><span class="s">"completed"</span><span class="p">,</span> <span class="s">"system"</span><span class="p">)</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">_notify</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">owner_email</span><span class="p">,</span> <span class="s">"All parties have signed."</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">DocStatus</span><span class="p">.</span><span class="n">PARTIALLY_SIGNED</span>

        <span class="k">return</span> <span class="s">"ok"</span>

    <span class="k">def</span> <span class="nf">decline</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">token</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
        <span class="n">signatory</span> <span class="o">=</span> <span class="nb">next</span><span class="p">((</span><span class="n">s</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">signatories</span> <span class="k">if</span> <span class="n">s</span><span class="p">.</span><span class="n">token</span> <span class="o">==</span> <span class="n">token</span><span class="p">),</span> <span class="bp">None</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">signatory</span><span class="p">:</span>
            <span class="k">return</span> <span class="s">"invalid_token"</span>
        <span class="n">signatory</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">SignatoryStatus</span><span class="p">.</span><span class="n">DECLINED</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_log</span><span class="p">(</span><span class="s">"declined"</span><span class="p">,</span> <span class="n">signatory</span><span class="p">.</span><span class="n">email</span><span class="p">)</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_notify</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">owner_email</span><span class="p">,</span> <span class="sa">f</span><span class="s">"</span><span class="si">{</span><span class="n">signatory</span><span class="p">.</span><span class="n">email</span><span class="si">}</span><span class="s"> declined to sign."</span><span class="p">)</span>
        <span class="k">return</span> <span class="s">"ok"</span>

    <span class="k">def</span> <span class="nf">void</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">DocStatus</span><span class="p">.</span><span class="n">VOIDED</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">_log</span><span class="p">(</span><span class="s">"voided"</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">owner_email</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">_notify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">recipient</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"[EMAIL] To: </span><span class="si">{</span><span class="n">recipient</span><span class="si">}</span><span class="s"> | </span><span class="si">{</span><span class="n">message</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>  <span class="c1"># replace with real email service
</span>
<span class="k">def</span> <span class="nf">expire_documents</span><span class="p">(</span><span class="n">documents</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="n">Document</span><span class="p">]):</span>
    <span class="n">now</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">doc</span> <span class="ow">in</span> <span class="n">documents</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">doc</span><span class="p">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">DocStatus</span><span class="p">.</span><span class="n">SENT</span> <span class="ow">and</span> <span class="n">now</span> <span class="o">&gt;</span> <span class="n">doc</span><span class="p">.</span><span class="n">expires_at</span><span class="p">:</span>
            <span class="n">doc</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">DocStatus</span><span class="p">.</span><span class="n">EXPIRED</span>
            <span class="n">doc</span><span class="p">.</span><span class="n">_log</span><span class="p">(</span><span class="s">"expired"</span><span class="p">,</span> <span class="s">"system"</span><span class="p">)</span>
</code></pre></div></div>

<p>Key points:</p>
<ul>
  <li>Each signatory gets a unique <code class="language-plaintext highlighter-rouge">token</code> (UUID) embedded in their signing URL — this is the idempotency mechanism. The server looks up the token, not a session or login.</li>
  <li><code class="language-plaintext highlighter-rouge">sign()</code> checks <code class="language-plaintext highlighter-rouge">already_signed</code> before doing any work — calling it twice with the same token is safe.</li>
  <li>The <code class="language-plaintext highlighter-rouge">audit_log</code> is append-only; nothing is ever removed from it.</li>
  <li><code class="language-plaintext highlighter-rouge">expire_documents</code> is meant to run as a cron job — scan all <code class="language-plaintext highlighter-rouge">sent</code> documents and flip any that are past their deadline.</li>
</ul>

<hr />

<p><strong>Anti-fraud system — CSV aggregation</strong>
Given a CSV file with columns <code class="language-plaintext highlighter-rouge">transaction_type</code>, <code class="language-plaintext highlighter-rouge">currency</code>, <code class="language-plaintext highlighter-rouge">date</code>, <code class="language-plaintext highlighter-rouge">amount</code>, sum all amounts grouped by <code class="language-plaintext highlighter-rouge">(date, transaction_type)</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">csv</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>

<span class="k">def</span> <span class="nf">aggregate</span><span class="p">(</span><span class="n">filename</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">float</span><span class="p">]:</span>
    <span class="n">totals</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">float</span><span class="p">]</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">float</span><span class="p">)</span>

    <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
        <span class="n">reader</span> <span class="o">=</span> <span class="n">csv</span><span class="p">.</span><span class="n">DictReader</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">reader</span><span class="p">:</span>
            <span class="n">key</span> <span class="o">=</span> <span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s">"date"</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="s">"transaction_type"</span><span class="p">])</span>
            <span class="n">totals</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">+=</span> <span class="nb">float</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s">"amount"</span><span class="p">])</span>

    <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">totals</span><span class="p">)</span>

<span class="c1"># Example output:
# {("2024-03-01", "charge"): 15000.0, ("2024-03-01", "refund"): 450.0, ...}
</span></code></pre></div></div>

<p>For fraud detection, flag groups that exceed a threshold:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">flag_suspicious</span><span class="p">(</span><span class="n">totals</span><span class="p">:</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">float</span><span class="p">],</span> <span class="n">threshold</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">10000.0</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">totals</span><span class="p">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">v</span> <span class="o">&gt;</span> <span class="n">threshold</span><span class="p">}</span>
</code></pre></div></div>

<p>Key points: <code class="language-plaintext highlighter-rouge">csv.DictReader</code> uses the header row as keys — no manual column indexing. <code class="language-plaintext highlighter-rouge">defaultdict(float)</code> starts every key at 0.0 so <code class="language-plaintext highlighter-rouge">+=</code> works without an existence check.</p>

<hr />

<p><strong>Brace Expansion I (LeetCode 1087)</strong>
Given a string like <code class="language-plaintext highlighter-rouge">"{a,b,c}d{e,f}"</code>, return all words it expands to, sorted. Each <code class="language-plaintext highlighter-rouge">{...}</code> block is a choice — pick exactly one character from it.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">expand</span><span class="p">(</span><span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
    <span class="n">groups</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="s">'{'</span><span class="p">:</span>
            <span class="n">j</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="s">'}'</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
            <span class="n">groups</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="p">:</span><span class="n">j</span><span class="p">].</span><span class="n">split</span><span class="p">(</span><span class="s">','</span><span class="p">)))</span>
            <span class="n">i</span> <span class="o">=</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">groups</span><span class="p">.</span><span class="n">append</span><span class="p">([</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">]])</span>
            <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="s">''</span><span class="p">]</span>
    <span class="k">for</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">groups</span><span class="p">:</span>
        <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">prefix</span> <span class="o">+</span> <span class="n">c</span> <span class="k">for</span> <span class="n">prefix</span> <span class="ow">in</span> <span class="n">result</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">group</span><span class="p">]</span>
    <span class="k">return</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>

<span class="c1"># expand("{a,b}c{d,e}") -&gt; ["acd", "ace", "bcd", "bce"]
</span></code></pre></div></div>

<p>Build the result incrementally: start with <code class="language-plaintext highlighter-rouge">['']</code> and for each group, take the Cartesian product of current prefixes × current group choices.</p>

<hr />

<p><strong>Brace Expansion II (LeetCode 1096)</strong>
Harder variant — braces can be nested and concatenation happens implicitly. <code class="language-plaintext highlighter-rouge">"{a{b,c}}"</code> → <code class="language-plaintext highlighter-rouge">["ab","ac"]</code>, <code class="language-plaintext highlighter-rouge">"{a,b}{c,{d,e}}"</code> → <code class="language-plaintext highlighter-rouge">["ac","ad","ae","bc","bd","be"]</code>.</p>

<p>Approach: recursive parser. A comma at depth 0 separates alternatives; everything else is concatenation. Each level returns a sorted deduplicated list of strings.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">braceExpansionII</span><span class="p">(</span><span class="n">expression</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
    <span class="k">def</span> <span class="nf">parse</span><span class="p">(</span><span class="n">expr</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
        <span class="n">groups</span> <span class="o">=</span> <span class="p">[[</span><span class="s">''</span><span class="p">]]</span>   <span class="c1"># list of "alternatives"; each alternative is a list of prefixes
</span>        <span class="n">depth</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>

        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">expr</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="s">'{'</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">depth</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">start</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span>
                <span class="n">depth</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="s">'}'</span><span class="p">:</span>
                <span class="n">depth</span> <span class="o">-=</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">depth</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">sub</span> <span class="o">=</span> <span class="n">parse</span><span class="p">(</span><span class="n">expr</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">i</span><span class="p">])</span>
                    <span class="n">groups</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">groups</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">sub</span><span class="p">]</span>
            <span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="s">','</span> <span class="ow">and</span> <span class="n">depth</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">groups</span><span class="p">.</span><span class="n">append</span><span class="p">([</span><span class="s">''</span><span class="p">])</span>
            <span class="k">elif</span> <span class="n">depth</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">groups</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span> <span class="o">+</span> <span class="n">c</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">groups</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span>

        <span class="k">return</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">w</span> <span class="k">for</span> <span class="n">g</span> <span class="ow">in</span> <span class="n">groups</span> <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">g</span><span class="p">))</span>

    <span class="k">return</span> <span class="n">parse</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
</code></pre></div></div>

<p>Key points:</p>
<ul>
  <li>Track <code class="language-plaintext highlighter-rouge">depth</code> to know when you’re inside a nested <code class="language-plaintext highlighter-rouge">{}</code> — only act on <code class="language-plaintext highlighter-rouge">,</code> and plain characters at depth 0.</li>
  <li>On closing <code class="language-plaintext highlighter-rouge">}</code> at depth 0: recursively parse the inner content and take the Cartesian product with the current group’s prefixes.</li>
  <li>Deduplicate with <code class="language-plaintext highlighter-rouge">set</code> at each level since <code class="language-plaintext highlighter-rouge">{a,a}</code> should produce <code class="language-plaintext highlighter-rouge">["a"]</code> not <code class="language-plaintext highlighter-rouge">["a","a"]</code>.</li>
</ul>

<hr />

<p><strong>Sales data aggregation</strong>
Given a list of sales records with varying input constraints (date range, region, product), calculate aggregate metrics. Focus on: grouping efficiently with dicts/defaultdict, handling missing keys gracefully, and clarifying the expected output format before writing any code.</p>

<hr />

<h2 id="resources">Resources</h2>

<ul>
  <li><a href="https://stripe.com/blog/engineering">Stripe engineering blog</a></li>
  <li>LeetCode — filter by company tag: Stripe</li>
  <li><a href="https://roundz.ai/company/stripe?tab=interviews">RoundZ — Stripe interview experiences</a></li>
  <li><a href="https://www.1point3acres.com/">1point3acres</a> — interview experiences and discussions, though the subscription is too costly</li>
</ul>]]></content><author><name>Seroze</name></author><category term="interview-prep" /><category term="stripe" /><category term="interview" /><category term="python" /><summary type="html"><![CDATA[My preparation notes for the Stripe interview process. Using Python throughout and Zed as the editor.]]></summary></entry></feed>