<?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="https://shuvraneelmitra.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://shuvraneelmitra.github.io/" rel="alternate" type="text/html" /><updated>2026-08-28T16:05:49+00:00</updated><id>https://shuvraneelmitra.github.io/feed.xml</id><title type="html">bubblewrap</title><subtitle>Notes on programming, music, ideas, and interesting corners of the internet.</subtitle><author><name>insipidintegrator</name></author><entry><title type="html">Minimum Swaps Between Two Permutations</title><link href="https://shuvraneelmitra.github.io/competitive-programming/probability/Min-Swaps-Between-Permutations/" rel="alternate" type="text/html" title="Minimum Swaps Between Two Permutations" /><published>2026-08-19T00:00:00+00:00</published><updated>2026-08-19T00:00:00+00:00</updated><id>https://shuvraneelmitra.github.io/competitive-programming/probability/Min-Swaps-Between-Permutations</id><content type="html" xml:base="https://shuvraneelmitra.github.io/competitive-programming/probability/Min-Swaps-Between-Permutations/"><![CDATA[<blockquote>
  <p><strong>Given two permutations of $[1…n]$, say $\pi_1(n)$ and $\pi_2(n)$, find the minimum number of swaps required to get from $\pi_1$ to $\pi_2$.</strong></p>
</blockquote>

<p>This is the easier version of the problem, since all the elements are guaranteed to be distinct. To go from $\pi_1$ to $\pi_2$, the $i$-th element of $\pi_1$ needs to go from its position $i$ in $\pi_1$ to a new position $j_i$ in $\pi_2$. It somewhat looks like this:</p>

<figure align="center">
  <img src="https://i.imgur.com/QLOCBfU.png" alt="Centered Image" />
</figure>

<p>This looks somewhat like a graph! When we untangle this gnarly mess and straighten out the curves, this is what we get:</p>

<figure align="center">
  <img src="https://i.imgur.com/cDHsJ8q.png" alt="Centered Image" />
</figure>

<p>This graph is special: each node has exactly one outdegree and one indegree. We note that such a graph will be composed entirely of loops, considering also singleton nodes with self-loops, if any.</p>

<blockquote>
  <p><strong>Theorem: Consider a digraph $G$ with $n$ nodes. If each node $i \in V_G$ has exactly one outdegree and one indegree, then $G$ consists entirely of disjoint cycles, including self-loops.</strong></p>

  <p><strong>Proof:</strong>  The idea that permutations can be decomposed into disjoint cycles comes from group theory. For more, see <a href="https://en.wikipedia.org/wiki/Permutation_graph">Permutation Graph</a>. For a proof of the theorem, look at <a href="https://math.stackexchange.com/a/2478207/1062486">this Math SE answer</a>.</p>
</blockquote>

<p>Now if we swap two non-consecutive elements in the graph, we simply swap the two nodes and nothing else happens. But if we swap two consecutive elements, say $1$ and $5$, then $5$ goes to the place it wanted to go, and gets out of the graph, with its out-degree pointing to itself. On the other hand, the place where $3$ wanted to go, earlier occupied by $5$, is now occupied by $1$ and so the outdegree of $3$ is directed towards $1$. Thus, in a cycle of size $k$, each swap of consecutive elements reduces the cycle length by $1$ by putting one element (the one in the pair from which the outdegree emanates) in the correct place, except when $k=2$ when it puts both the elements in their correct place. So to demolish a cycle of length $k$, we need exactly $k - 1$ swaps.</p>

<p>Thus, if the total number of nodes in the graph is $n$ and the total number of disjoint connected components is $c$, then the minimum number of swaps needed is $\sum_{C \text{is a connected component}}(\text{Number of nodes in C} - 1) = n - c$</p>

<p>One special case to consider is that of the positions which are already in place, i.e. $i = j_i$. These will be represented in the graph by nodes which have self-loops and no outside connections, thus forming a singleton. Of course, involving these in a swap can never be optimal, since we will have to again waste a swap operation to bring it back to the correct place. These will, notably, not disturb the formula since we need $1-1=0$ swaps to put it to its correct place.</p>

<p>Thus the final algorithm to find the minimum number of swaps for two given permutations as input is:</p>

<blockquote>
  <ol>
    <li>Convert the transformation from permutation $\pi_1$ to $\pi_2$ into a permutation graph</li>
    <li>Find the number of connected components in the graph via a standard algorithm (such as DFS), say it is k.</li>
    <li>The answer is $n - k$.</li>
  </ol>
</blockquote>

<p>Now, sitting in the returning office cab and looking at <a href="https://www.youtube.com/watch?v=vfsrJB_yfo0">this video</a>, my mind immediately spawns the following problem:</p>

<blockquote>
  <p><strong>Given two permutations of $[1…n]$, say $\pi_1(n)$ and $\pi_2(n)$, let $f(\pi_1, \pi_2)$ be the minimum number of swaps required to get from $\pi_1$ to $\pi_2$. Find $\mathbb E[f(\pi_1, \pi_2)]$ where $\pi_1(n)$ and $\pi_2(n)$ are sampled uniformly from the set of $n!$ permutations of $[1…n]$.</strong></p>
</blockquote>

<p>A few great takes on this puzzle can be found <a href="https://math.stackexchange.com/q/165407/1062486">here</a>.</p>]]></content><author><name>insipidintegrator</name></author><category term="Competitive-Programming" /><category term="Probability" /><summary type="html"><![CDATA[An interesting question that led to another one]]></summary></entry><entry><title type="html">Interesting Internet Artifacts</title><link href="https://shuvraneelmitra.github.io/random/Interesting-Internet/" rel="alternate" type="text/html" title="Interesting Internet Artifacts" /><published>2026-02-21T00:00:00+00:00</published><updated>2026-02-21T00:00:00+00:00</updated><id>https://shuvraneelmitra.github.io/random/Interesting-Internet</id><content type="html" xml:base="https://shuvraneelmitra.github.io/random/Interesting-Internet/"><![CDATA[<h2 id="a-collection-of-the-most-hol-up-thats-nice-things-ive-found-on-the-internet"><strong>A collection of the most “<em>hol’ up, that’s nice!</em>” things I’ve found on the internet</strong></h2>

<blockquote>
  <p>As the saying goes, the internet is full of wacky curiosities, some of which you keep coming back to years after you first discovered them, out of the very human need to internet-surf your time away, rather than out of necessity. I present to you my collection of, what I like to call, “<em>fun stuff</em>”.</p>
</blockquote>

<ol>
  <li>
    <p><a href="https://neal.fun/">Neal.fun</a>: I personally believe that no “fun internet websites” list can be complete without a mention of the legendary neal.fun page. I personally love the “<a href="https://neal.fun/perfect-circle/">Draw a Perfect Circle</a>” challenge the most, not only because it reminds me of <a href="https://en.wikipedia.org/wiki/A_Perfect_Circle">A Perfect Circle</a>, but also because figuring out a formula to calculate a percentage score for an “almost-circle” that makes sense is a nice math challenge.</p>
  </li>
  <li>
    <p><a href="https://sandtris.com/">sandtris</a>: Tetris, but with a twist. Do try it out.</p>
  </li>
  <li>
    <p><a href="https://www.pointlesssites.com/">pointlesssites</a>: A huge catalogue of “interesting” stuff that is enough to bash <em>this</em> list into obsolescence. Have fun exploring the website, for you might look up from your screen to find 2 years have passed by while you were digging into rabbitholes in this page.</p>
  </li>
  <li>
    <p><a href="https://ncase.me/trust/">The Evolution of Trust</a>: Simply put, a cool guide to Game Theory without seeming like one.</p>
  </li>
  <li>
    <p><a href="https://ncase.itch.io/wbwwb">We Become What We Behold</a>: A nice commentary on how <a href="https://en.wikipedia.org/wiki/Yellow_journalism">yellow journalism</a> impacts how we feel about others in society, and how mass media has a huge leverage on the general public sentiment towards an event or a group of people. Makes you stop and think.</p>
  </li>
  <li>
    <p><a href="https://ncase.me/">Nicky Case</a>: Another creator who makes nice engaging “games” which sometimes double up as learning tools. The above two entries are actually made by Case himself but I put them separately because I discovered them independently of his general website where these are also hosted.</p>
  </li>
  <li>
    <p><a href="https://www.zenpencils.com/">Zen Pencils</a>: A set of ~200 beautiful webcomics, each of which takes a memorable quote, and illustrates life into it.</p>
  </li>
  <li>
    <p><a href="https://mathwithbaddrawings.com/">Math With Bad Drawings</a>: I can almost smell the marker ink from those drawings.</p>
  </li>
  <li>
    <p><a href="https://foddy.net/legacy/Athletics.html">QWOP</a>: Built by Bennett Foddy, a prolific game designer, this game is more difficult than gathering yourself to study for your college exams. Contact me if you can run the full 100 metres on a regular basis ;) He’s made variations too, such as <a href="https://foddy.net/blog/2012/08/clop/">CLOP</a> and <a href="https://foddy.net/blog/2012/02/2qwop/">2QWOP</a>.</p>
  </li>
  <li>
    <p><a href="https://www.decisionproblem.com/paperclips/">Universal Paperclips</a>: You start off with one goal: to make as many paperclips as possible. Time goes by until that goal fades into distance, with Quantum Computing, Stock Market Investing, Strategy Modeling and Space Exploration taking center stage until … all the matter in the universe is turned into paperclips and you are the only non-paperclip object in the universe. Do you have the gumption to sacrifice yourself for the 
greater good of having as many paperclips as possible?</p>
  </li>
  <li>
    <p><a href="https://playspent.org/">Play Spent</a>: Appreciate all the riches that you have.</p>
  </li>
  <li>
    <p><a href="https://www.onedayyoullfindyourself.com/">One Day You Will Find Yourself …</a>: Unsolicited advice is sometimes welcome, especially in times of boredom!</p>
  </li>
  <li>
    <p><a href="https://hoaxes.org/">The Museum of Hoaxes</a>: Some hoaxes are purely for satirical value, while some have ulterior motives behind them. Click on to uncover a world of trickery!</p>
  </li>
  <li>
    <p><a href="http://www.tanyakhovanova.com/coffins.html">Math</a>: One for the math nerds; this problem set has much historical value. Description of thd contents: simple solutions which are difficult to find.</p>
  </li>
  <li>
    <p><a href="https://www.youtube.com/watch?v=WfGMYdalClU">MAN</a>: We are moving into the more poignant territory now. What happens when a species dominates the planet and carries out mass extermination of all the remaining species, which just want to survive in harmony with the natural laws? The <a href="https://www.youtube.com/watch?v=p7LDk4D3Q3U">sequel</a> is no less awesome.</p>
  </li>
  <li>
    <p><a href="https://poki.com/en/g/there-is-no-game">There is No Game</a>: Why click on it when there is, in fact, no game? Let’s move on to the next entry in the list…</p>
  </li>
  <li>
    <p><a href="https://literature-clock.jenevoldsen.com/">Literature Clock</a>: A very cool website for all book lovers; this website tells the time down to the minute with a quote from a book.</p>
  </li>
  <li>
    <p><a href="https://texnique.xyz/">TEXnique</a>: Competitive ranked TEXing is, apparently, a thing.</p>
  </li>
  <li>
    <p><a href="https://waitbutwhy.com/">Wait But Why</a> Been a lifesaver on multiple occasions.</p>
  </li>
</ol>]]></content><author><name>insipidintegrator</name></author><category term="Random" /><summary type="html"><![CDATA[This is where your attention span comes in clutch]]></summary></entry><entry><title type="html">Codeforces 1777B: Emordnilap</title><link href="https://shuvraneelmitra.github.io/competitive-programming/Codeforces-1777B/" rel="alternate" type="text/html" title="Codeforces 1777B: Emordnilap" /><published>2025-11-07T00:00:00+00:00</published><updated>2025-11-07T00:00:00+00:00</updated><id>https://shuvraneelmitra.github.io/competitive-programming/Codeforces-1777B</id><content type="html" xml:base="https://shuvraneelmitra.github.io/competitive-programming/Codeforces-1777B/"><![CDATA[<blockquote>
  <p>Given a permutation $p$ of $n$ numbers, we create an array $a$ consisting of $2n$ numbers, which is equal to $p$ concatenated with its
reverse. We then define the beauty of $p$ as the number of inversions in $a$. Your task is to find the sum of beauties of all $n!$ 
permutations of size $n$. Print the remainder we get when dividing this value by $1000000007$.</p>
</blockquote>

<p>Let us call the reverse of $p$ as $\operatorname {rev}(p)$, then we notice that if $0\leq i \lt j \lt 2n$ form an inversion in $a$ then either one of these three cases must occur:</p>

<ul>
  <li>$i \in p, \quad j \in p$</li>
  <li>$i \in p, \quad j \in \operatorname {rev}(p)$</li>
  <li>$i \in \operatorname {rev}(p), \quad j \in \operatorname {rev}(p)$</li>
</ul>

<p>Since we are going to iterate over all permutations of $p$, we note that the first and third cases are exactly the same and we write, considering $\operatorname{inv}(p)$ to be the number of inversions in $p$, and $\pi(\cdot)$ being the set of all permutations of an array:</p>

\[\operatorname{inv}(a) = \operatorname{inv}(p) + \operatorname {inv}(\operatorname {rev}(p)) + \dfrac{n(n-1)}{2}\]

<p>Summing over all the $n!$ permutations of $p = $ {$1 \dots n$} we get</p>

\[\displaystyle \sum\operatorname{inv}(a) = \sum\operatorname{inv}(p) + \sum\operatorname {inv}(\operatorname {rev}(p)) + n!\cdot\dfrac{n(n-1)}{2}\tag{1}\]

\[=2\sum\operatorname{inv}(p) + n!\cdot\dfrac{n(n-1)}{2}\tag{2}\]

<p>Now the task of finding the sum of the number of inversions over all permutations of [1…n] is something we must tackle. $(**)$</p>

<h2 id="edit"><strong>EDIT</strong></h2>
<p><small>09 November 2024</small>
<br />
Wait! This approach makes the problem significantly harder than it needs to be.</p>

<h4 id="approach-1"><strong>Approach 1</strong></h4>
<p>Pick any two numbers (not indices) $x$ and $y$ in $p$. In $a$, they can appear either in the order $x\ y \ y \ x$ or $y \ x \ x \ y$, in both of which cases we get a total of two inversions. Thus for any permutation $p$, its beauty is given by $2\cdot \displaystyle\binom{n}{2} = n(n-1)$, independent of the specific permutation $p$.</p>

<p>Hence the total number of inversions is simply this constant multiplied by the number of possible permutations, which is $n!\cdot n(n-1)$.</p>

<h4 id="approach-2"><strong>Approach 2</strong></h4>
<p>Suppose we pick two indices $i, j$ from $p$. If $(i, j)$ is an inversion in the first half of $a$, then $(i + n, j + n)$ will not be an inversion in the second half of $a$. However, if $(i, j)$ is <em>NOT</em> an inversion in the first half of $a$, then $(i + n, j + n)$ <em>MUST</em> be an inversion in the second half of $a$.</p>

<p>This simply means that any pair of indices $(i, j)$ from $p$ will give us exactly one inversion in $a$, and there are $\displaystyle \binom n2$ such pairs. Add to this the cross inversion term from $(2)$ and we get the same answer again, $n!\cdot n(n-1)$.</p>

<hr />

<p>So the lesson learnt is sometimes we might need to stop a little bit early and look at the problem from a holistic point of view instead of simplifying the expression as much as possible.</p>

<p>$(**)$<a href="https://math.stackexchange.com/questions/1649339/number-of-inversions">A really nice Math SE post regarding the total number of inversions across all permutations of $[1…n]$</a></p>]]></content><author><name>insipidintegrator</name></author><category term="Competitive-Programming" /><summary type="html"><![CDATA[Just did contribution problems, look what I found!]]></summary></entry><entry><title type="html">Codeforces 1840B: Binary Cafe</title><link href="https://shuvraneelmitra.github.io/competitive-programming/Codeforces-1840B/" rel="alternate" type="text/html" title="Codeforces 1840B: Binary Cafe" /><published>2025-11-07T00:00:00+00:00</published><updated>2025-11-07T00:00:00+00:00</updated><id>https://shuvraneelmitra.github.io/competitive-programming/Codeforces-1840B</id><content type="html" xml:base="https://shuvraneelmitra.github.io/competitive-programming/Codeforces-1840B/"><![CDATA[<blockquote>
  <p>Once upon a time, Toma found himself in a binary cafe. It is a very popular and unusual place.</p>

  <p>The cafe offers visitors $k$ different delicious desserts. The desserts are numbered from $0$ to $k−1$. The cost of the $i$-th dessert is $2^i$ coins, because it is a binary cafe! Toma is willing to spend no more than $n$ coins on tasting desserts. At the same time, he is not interested in buying any dessert more than once, because one is enough to evaluate the taste.</p>

  <p>In how many different ways can he buy several desserts (possibly zero) for tasting?</p>
</blockquote>

<p>Upfront, this looks like a hard one: formally stated, we need to find the number of (potentially empty) subsets $S \in$ {$0, 1, \dots, k-1$} such that \(\displaystyle \sum_{i\in S}2^i \leq n.\)
But when you start thinking in binary, this simplifies down to absolutely nothing! The cost when you choose the $i$ th object is $(c_i)_2 = 10000\dots 0$ where there are $i-1$ zeros. Thus, choosing a subset $S$ corresponds to activating the $j$ th bit from the right in the total cost. Eg. choose {$0, 2, 7$} and the cost is $2^0 + 2^2 + 2^7 = 128 + 4 + 1 = 133$ which corresponds exactly to $1000101$: the $0$ th, $2$ nd and $7$ th bits are <em>on</em>.</p>

<p>We, then, only need to find the number of ways we can choose places in the $k$ positions provided to us such that this combination is never greater than $n$. If the number of total places, $k$, is less than the number of bits in n, then no matter what we do, even if we choose all the elements we will still ensure total cost to be less than $n$. There are $2^k$ ways to do this, including the empty set.</p>

<p>On the other hand, if this is not the case, we have $n$ as our bottleneck. Here we note that if a bit is unset in $n$, it can <strong>never</strong> be selected when all the leftward set bits are selected. This gives rise to the following algorithm for this case:</p>

<blockquote>
  <ul>
    <li>Initialise $sum = 0$.</li>
    <li>For each set bit in $n$, add $2^\text{number of bits to the right of the bit}$ to $sum$. This represents the number of choices when $b_i$ is turned off and all the bits to the left of $b_i$ that were set in $n$ are set.</li>
    <li>Finally, add $1$ to $sum$ to account for the total cost being exactly equal to $n$, which is always possible given $k &gt; \lceil{\lg n}\rceil$.</li>
  </ul>
</blockquote>

<p>Thus our final code is:</p>
<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;bits/stdc++.h&gt;</span><span class="cp">
</span><span class="k">typedef</span> <span class="kt">long</span> <span class="kt">long</span> <span class="n">ll</span><span class="p">;</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="cp">#define F first
#define S second
#define rep(i, init, upper) for(size_t i=init; i&lt;upper; i++)
</span>
<span class="kt">int</span> <span class="nf">binpow</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">){</span>
    <span class="kt">int</span> <span class="n">result</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="n">b</span><span class="p">){</span>
        <span class="k">if</span><span class="p">(</span><span class="n">b</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="n">result</span> <span class="o">*=</span> <span class="n">a</span><span class="p">;</span>
        <span class="n">a</span> <span class="o">*=</span> <span class="n">a</span><span class="p">;</span>
        <span class="n">b</span> <span class="o">/=</span> <span class="mi">2</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="n">solve</span><span class="p">(){</span>
    <span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="n">k</span><span class="p">;</span>
    <span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">n</span> <span class="o">&gt;&gt;</span> <span class="n">k</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">total_bits</span> <span class="o">=</span> <span class="n">CHAR_BIT</span> <span class="o">*</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>
    <span class="kt">int</span> <span class="n">leading_zeros</span> <span class="o">=</span> <span class="n">__builtin_clz</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
    <span class="kt">int</span> <span class="n">msb_pos</span> <span class="o">=</span> <span class="n">total_bits</span> <span class="o">-</span> <span class="n">leading_zeros</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>

    <span class="k">if</span><span class="p">(</span><span class="n">k</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="n">msb_pos</span><span class="p">)</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">binpow</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="k">else</span><span class="p">{</span>
        <span class="kt">bool</span> <span class="n">is_set</span><span class="p">[</span><span class="n">total_bits</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="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">total_bits</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="n">is_set</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;&gt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">&amp;</span> <span class="mi">1</span><span class="p">;</span>

        <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// for when total price is exactly n</span>
        <span class="kt">int</span> <span class="n">power2</span> <span class="o">=</span> <span class="mi">1</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="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">&lt;</span><span class="n">total_bits</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
            <span class="k">if</span><span class="p">(</span><span class="n">is_set</span><span class="p">[</span><span class="n">i</span><span class="p">])</span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">power2</span><span class="p">;</span>
            <span class="n">power2</span> <span class="o">*=</span> <span class="mi">2</span><span class="p">;</span>
        <span class="p">}</span>
        <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">sum</span> <span class="o">&lt;&lt;</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">(){</span>
    <span class="n">ios_base</span><span class="o">::</span><span class="n">sync_with_stdio</span><span class="p">(</span><span class="nb">false</span><span class="p">);</span>
    <span class="n">cin</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="nb">nullptr</span><span class="p">);</span> <span class="n">cout</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="nb">nullptr</span><span class="p">);</span>
    <span class="cp">#ifndef ONLINE_JUDGE
</span>        <span class="n">freopen</span><span class="p">(</span><span class="s">"../input.txt"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">,</span> <span class="n">stdin</span><span class="p">);</span>
        <span class="n">freopen</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="n">stdout</span><span class="p">);</span>
    <span class="cp">#endif
</span>    <span class="kt">int</span> <span class="n">t</span><span class="p">;</span>
    <span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">t</span><span class="p">;</span>
    <span class="k">while</span><span class="p">(</span><span class="n">t</span><span class="o">--</span><span class="p">){</span>
        <span class="n">solve</span><span class="p">();</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>]]></content><author><name>insipidintegrator</name></author><category term="Competitive-Programming" /><summary type="html"><![CDATA[A nice problem where thinking in binary pops up unexpectedly]]></summary></entry><entry><title type="html">Vicarious and the Bloodthirstiness of Human Nature</title><link href="https://shuvraneelmitra.github.io/music/Vicarious/" rel="alternate" type="text/html" title="Vicarious and the Bloodthirstiness of Human Nature" /><published>2025-11-07T00:00:00+00:00</published><updated>2025-11-07T00:00:00+00:00</updated><id>https://shuvraneelmitra.github.io/music/Vicarious</id><content type="html" xml:base="https://shuvraneelmitra.github.io/music/Vicarious/"><![CDATA[]]></content><author><name>insipidintegrator</name></author><category term="Music" /><summary type="html"><![CDATA[Sometimes it's the most direct TOOL songs that hit you]]></summary></entry><entry><title type="html">Resolving the classic diamond problem: a perspective on C3 linearization</title><link href="https://shuvraneelmitra.github.io/programming/C3/" rel="alternate" type="text/html" title="Resolving the classic diamond problem: a perspective on C3 linearization" /><published>2024-12-02T00:00:00+00:00</published><updated>2024-12-02T00:00:00+00:00</updated><id>https://shuvraneelmitra.github.io/programming/C3</id><content type="html" xml:base="https://shuvraneelmitra.github.io/programming/C3/"><![CDATA[<figure align="center">
  <img src="https://miro.medium.com/v2/resize:fit:713/0*Tcyw6uNQJyQnIals.jpg" alt="Centered Image" />
</figure>

<p>While creating software from scratch to solve our problems, we often face many design choices. One of them that an object-oriented programmer invariably has to deal with is <strong>how to structure the polymorphic behaviour</strong> of their classes and subclasses. It is here that we start to appreciate the famous <strong>diamond problem</strong> and its many nuances.</p>

<p>You probably got a lot of your features from your mother, and also a lot of them from your father. In biological systems, this process of choosing which feature is inherited from whom is inherently random, and that causes the vast diversity in the world that we celebrate (or at least, <em>should</em> celebrate). However, as software engineers, our task is cut out and we cannot have our child classes behaving randomly, with their attributes a chaotic amalgamation of similar attributes defined in their parent classes. So we need to find a way to address this problem and define, deterministically, which attribute is inherited from which class.</p>

<figure align="center">
  <img src="https://miro.medium.com/v2/resize:fit:298/1*uktY6SYOr2zIZFGfbSeB-g.jpeg" alt="Centered Image" />
  <figcaption>The diamond problem visualised</figcaption>
</figure>

<p>Suppose we have the above class design. B is a child of A, C is a child of A, and D is a child of both B and C. This is a classic case of <strong>multiple inheritance.</strong> In the case that B and C have some common methods which are defined differently, how do we decide which implementation D should inherit? In other words, how do we implement a deterministic <strong>order</strong> in which the <strong>methods</strong> in the child classes are <strong>resolved</strong>?</p>

<p>Python does this through a special object called the <strong>Method Resolution Order.</strong> The MRO is a list of classes and subclasses which tells us the order in which to look for any method (which is being called) of a child class in all the classes in its inheritance hierarchy. As an example, let us implement the very simple inheritance structure A -&gt; B -&gt; C:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class A:  
  def func():  
    pass  
  
class B(A):  
  def func():  
    pass  
  
class C(B):  
  pass
</code></pre></div></div>

<p>Printing <code class="language-plaintext highlighter-rouge">C.mro</code> gives me <code class="language-plaintext highlighter-rouge">&lt;built-in method mro of type object at 0x5685f2d2d910&gt;</code> and calling the object with <code class="language-plaintext highlighter-rouge">C.mro()</code> gives us the order [C, B, A], which is intuitively expected. Now, in the case of a much more complex inheritance hierarchy, how do we define a deterministic MRO?</p>

<p>In Python, this is done using an algorithm called <strong>C3 Linearization.</strong> This is a linearization technique which takes into account the depth of each parent class in the inheritance hierarchy. The output of this algorithm is such that superclasses lower down in the inheritance hierarchy are searched first when looking for a method in the child class. The main step of the algorithm looks like a simple <strong>divide-and-conquer</strong> step:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C3_Linearization(C) = [C] + merge(C3_Linearization(Parents(C)), Parents(C))
</code></pre></div></div>

<p>The merge of Parents’ linearizations and Parents list is done by selecting the <strong><em>first</em></strong> head (the first entry of a list) of the lists which does not appear in the tail (all elements of a list <em>except the first</em>) of any of the lists. A singleton list is simply a head by itself. The rationale behind this first step is that any superclass that is just a head without appearing in any tail is much closer to the child semantically than any other parent which is also a parent of the child class’s parent (which is what appearing in the tail implies). Note, that a <strong>good head</strong> may appear as the first element in multiple lists at the same time, but it is forbidden to appear anywhere else.</p>

<p>The selected element is removed from all the lists where it appears as a head and appended to the output list. This is repeated until all remaining lists are exhausted. If at some point no good head can be selected, because the heads of all remaining lists appear in any one tail of the lists, then our algorithm fails because:</p>

<ol>
  <li>A class X appearing as head means that it is a parent of some layer of child classes at the given step in the algorithm</li>
  <li>A class X appearing in the tail of a list implies that it is above the head of the list in the inheritance hierarchy.</li>
</ol>

<p>Thus, if the heads of all remaining lists appear in any one tail of the lists, this implies a <strong>cyclic class hierarchy which, simply, cannot be resolved.</strong> In that case we might still run our algorithm with the additional check of not re-entering an already visited class.</p>

<h2 id="let-us-have-an-example">Let us have an example.</h2>

<figure align="center">
  <img src="https://miro.medium.com/v2/resize:fit:875/0*gp-NPOOO3vIpyjmb.png" alt="Centered Image" />
</figure>

<p>In this reasonably complex class hierarchy, we have</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class O  
class A extends O  
class B extends O  
class C extends O  
class D extends O  
class E extends O  
class K1 extends C, A, B  
class K3 extends A, D  
class K2 extends B, D, E  
class Z extends K1, K3, K2
</code></pre></div></div>

<p>the linearization of Z is computed as</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>L(O)  := [O]                                                  
// the linearization of O is trivially the singleton list [O],   
// because O is the ultimate base class   
   
L(A)  := [A] + merge(L(O), [O])    
    = [A] + merge([O], [O])  
    = [A, O]                           
   
L(B)  := [B, O] // linearizations of B, C, D and E are computed similarly as A  
L(C)  := [C, O]  
L(D)  := [D, O]  
L(E)  := [E, O]  
  
L(K1) := [K1] + merge(L(C), L(B), L(A), [C, A, B])            
// first, find the linearization of K1's parents, L(C), L(B), and L(A)  
// and merge them with the parent list [C, A, B]  
      = [K1] + merge([C, O], [B, O], [A, O], [C, A, B])      
// class C is a good head for the first merge step, because it only   
// appears as the head of the first and last lists  
      = [K1, C] + merge([O], [B, O], [A, O], [A, B])         
// class O is not a good candidate for the next merge step, because it  
// also appears in the tails of list 2 and 3. Class B is also not good;   
// but class A is a good candidate.  
      = [K1, C, A] + merge([O], [B, O], [O], [B])            
// class B is a good candidate; class O still appears in the tail of list 2  
      = [K1, C, A, B] + merge([O], [O], [O])                 
// finally, class O is a valid candidate, which also exhausts all   
// remaining lists and gives us our final linearization  
      = [K1, C, A, B, O]  
  
L(K3) := [K3] + merge(L(A), L(D), [A, D])  
      = [K3] + merge([A, O], [D, O], [A, D])               // select A  
      = [K3, A] + merge([O], [D, O], [D])                  // select D  
      = [K3, A, D] + merge([O], [O])                       // select O  
      = [K3, A, D, O]  
  
L(K2) := [K2] + merge(L(B), L(D), L(E), [B, D, E])  
      = [K2] + merge([B, O], [D, O], [E, O], [B, D, E])    // select B  
      = [K2, B] + merge([O], [D, O], [E, O], [D, E])       // select D  
      = [K2, B, D] + merge([O], [O], [E, O], [E])          // select E  
      = [K2, B, D, E] + merge([O], [O], [O])               // select O  
      = [K2, B, D, E, O]  
  
L(Z)  := [Z] + merge(L(K1), L(K3), L(K2), [K1, K3, K2])  
      = [Z] + merge([K1, C, A, B, O], [K3, A, D, O], [K2, B, D, E, O], [K1, K3, K2])    // select K1  
      = [Z, K1] + merge([C, A, B, O], [K3, A, D, O], [K2, B, D, E, O], [K3, K2])        // select C  
      = [Z, K1, C] + merge([A, B, O], [K3, A, D, O], [K2, B, D, E, O], [K3, K2])        // select K3  
      = [Z, K1, C, K3] + merge([A, B, O], [A, D, O], [K2, B, D, E, O], [K2])            // select A  
      = [Z, K1, C, K3, A] + merge([B, O], [D, O], [K2, B, D, E, O], [K2])               // select K2  
      = [Z, K1, C, K3, A, K2] + merge([B, O], [D, O], [B, D, E, O])                     // select B  
      = [Z, K1, C, K3, A, K2, B] + merge([O], [D, O], [D, E, O])                        // select D  
      = [Z, K1, C, K3, A, K2, B, D] + merge([O], [O], [E, O])                           // select E  
      = [Z, K1, C, K3, A, K2, B, D, E] + merge([O], [O], [O])                           // select O  
      = [Z, K1, C, K3, A, K2, B, D, E, O]
</code></pre></div></div>

<h2 id="now-for-another-example">Now for another example!</h2>

<blockquote>
  <p>The output of this algorithm is such that superclasses lower down in the inheritance hierarchy are searched first when looking for a method in the child class.</p>
</blockquote>

<p>We’ll now understand this line using the following example:</p>

<p align="center">
  <img src="https://miro.medium.com/v2/resize:fit:660/1*h2-TtcwJytOBvW_iHqv2zw.png" alt="Centered Image" />
</p>

<p>Now D inherits from both C, placed at depth 2, and B, which is placed at depth 1. In this case the linearization of D will be calculated as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>L(O)  := [O]                                                  
  
L(A)  := [A] + merge(L(O), [O])    
    = [A] + merge([O], [O])  
    = [A, O]                           
   
L(B)  := [B, O]  
  
L(C) := [C] + merge(L(B), L(A), [B, A])  
      = [C] + merge([B, O], [A, O], [B, A])  
      = [C, B] + merge([O], [A, O], [A]) // choose B  
      = [C, B, A] + merge([O], [O]) // choose A  
      = [C, B, A, O]  
  
L(D) := [D] + merge(L(B), L(C), [C, B])  
      = [D] + merge([B, O], [C, B, A, O], [C, B])  
      = [D, C] + merge([B, O], [B, A, O], [B]) // choose C  
      = [D, C, B] + merge([O], [A, O]) // choose B  
      = [D, C, B, A] + merge([O], [O]) // choose A  
      = [D, C, B, A, O]
</code></pre></div></div>

<p>As we see, the superclass C comes first in the MRO generated by our algorithm since C is below B in the inheritance hierarchy. A crucial point to note is that the exact form of MRO depends on the order of the classes in the definition of our inheritance relationship. So writing</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>class B(A, O):  
  pass  
  
# and  
   
class B(O, A):  
  pass
</code></pre></div></div>

<p>should be expected to return different behaviour for the MRO, and can be tested readily in Python.</p>

<p>If you have some previous experience in algorithms, you would be curious about the time complexity of the algorithm. The algorithm is linear in the number of classes in the final MRO, plus the total number of relationships that we define from one class to another, since during the merge step we find the linearizations of the parents which recursively visits all the superclasses till the base class exactly once and traverses each relationship once. A new perspective can be found if we simply realize that <strong>the inheritance hierarchy, when visualised, is simply a directed graph, with nodes as classes and edges as relationships!</strong></p>

<h6 id="the-c3-linearization-algorithm-can-simply-be-represented-as-a-topological-sorting-of-the-directed-graph-of-the-inheritance-hierarchy-also-the-fact-that-a-cyclic-inheritance-relationship-cannot-be-formed-into-an-mro-without-additional-conditions-and-compromises-is-a-direct-analogue-of-the-fact-that-only-directed-acyclic-graphs-can-be-linearized-using-topological-sorting-this-also-gives-credence-to-the-claim-of-linear-on--m-complexity-in-n-the-number-of-nodes-plus-m-the-number-of-edges"><strong>The C3 linearization algorithm can simply be represented as a topological sorting of the directed graph of the inheritance hierarchy. Also, the fact that a cyclic inheritance relationship cannot be formed into an MRO without additional conditions and compromises, is a direct analogue of the fact that only Directed ACYCLIC graphs can be linearized using topological sorting. This also gives credence to the claim of linear O(n + m) complexity in n, the number of nodes, plus m, the number of edges.</strong></h6>

<h2 id="concluding-thoughts">Concluding thoughts</h2>

<p>But are complex inheritance structures actually useful? Consider the following structure:</p>

<p align="center">
  <img src="https://miro.medium.com/v2/resize:fit:408/0*JJvUw1NHVMU0abza.png" alt="Centered Image" />
</p>

<p>Here, we model a GradTeachingFellow as both a Student and a Teacher. But picture this: how would you want to inherit getDepartment() for GradTeachingFellow? They might be student in one department and teach in another one. This calls for a decision to be taken for each such attribute, which is now equivalent to simply implementing all the methods of the GradTeachingFellow class using overrides, thus reducing the inheritance structure purely down to semantic significance.</p>

<p>We conclude with the air that having a complicated inheritance structure as the ones described above must be readily avoided for the sake of maintainability and cleanliness of code. A good software design bypasses the need for complex relationships such as circular inheritance and heavy calculations like these are best left for academic purposes!</p>

<h3 id="references">References:</h3>

<ol>
  <li><a href="https://en.wikipedia.org/wiki/C3_linearization">https://en.wikipedia.org/wiki/C3_linearization</a></li>
  <li><a href="https://stackoverflow.com/questions/561729/can-the-diamond-problem-be-really-solved">https://stackoverflow.com/questions/561729/can-the-diamond-problem-be-really-solved</a></li>
</ol>

<p><em>(Migrated from Medium on 17 August 2026)</em></p>]]></content><author><name>insipidintegrator</name></author><category term="Programming" /><summary type="html"><![CDATA[Ever met the diamond problem while creating your software? Let’s take a deep dive to solve one of the classic problems in software design]]></summary></entry><entry><title type="html">Demystifying Decorators: What are they and why do you need them?</title><link href="https://shuvraneelmitra.github.io/programming/Decorators/" rel="alternate" type="text/html" title="Demystifying Decorators: What are they and why do you need them?" /><published>2023-07-23T00:00:00+00:00</published><updated>2023-07-23T00:00:00+00:00</updated><id>https://shuvraneelmitra.github.io/programming/Decorators</id><content type="html" xml:base="https://shuvraneelmitra.github.io/programming/Decorators/"><![CDATA[<p><img src="https://miro.medium.com/v2/resize:fit:875/1*bLVASuOHihpXDKLo0n9NfA.png" alt="" /></p>

<p>While starting out with more advanced topics in Python, one frequently encounters a formidable beast called ‘Decorators’. While students usually learn the syntax and how to use the ‘@’ symbol above function definitions before moving on, decorators are much more fundamental to software design than they seem at first.</p>

<p>Decorators are a software ‘Design Pattern’ in OOPS: they are templates used to solve a specific problem in software design. <strong>Now, what is the problem that we would like to solve?</strong> We would like to have objects that fulfil one small, specific function (in keeping with the <em>Single Responsibility Principle</em>) and whose functionality can be <strong>extended</strong> without modifying their code (satisfying the <em>Open-Closed Principle</em>). We would also like to be able to add multiple functionalities, flexibly, to objects at runtime without affecting other objects from the same class.</p>

<h2 id="why-decorators">WHY DECORATORS?</h2>

<p><strong>EXAMPLE</strong>: Suppose you go to buy some pizza. The pizza house has lots of toppings, sauces and vegetables, and allows customers to fully customise their pizzas. <strong>We want to design a software that calculates the price of the pizza based on the customer’s choice of ingredients.</strong></p>

<p>Now, one intuitive approach to this problem would be subclassing. In this approach, we have a root class called Pizza (with a cost() method), and then we add layers of subclasses to it, with each subclass representing a unique variety of pizza that can be concocted from the given menu. Suppose the available menu is as follows:</p>

<p><strong>CRUST</strong>: More cheese, Less cheese</p>

<p><strong>TOPPINGS</strong>: Chilli flakes, black pepper, oregano, Sriracha</p>

<p><strong>VEGGIES</strong>: Onions, tomatoes, black/green olives, smoked beans, pineapple</p>

<p><strong>NON-VEG</strong>: Grilled chicken, smoked ham</p>

<p>Of course, each individual item has its own price which gets added to a base price.</p>

<p><img src="https://miro.medium.com/v2/resize:fit:875/1*2Se0E_Tj0VKKrP9k9hvHDg.png" alt="" /></p>

<p>The subclassing approach, with just a few subclasses from the second layer shown.</p>

<p>We have two classes, ‘<em>More cheese</em>’ and ‘<em>Less cheese’</em>, which inherit from the Pizza class, but with their own cost() methods. Further, we will have another layer with added on toppings, which will contain pizzas like ‘<em>More cheese with chilli flakes and black pepper’</em>, ‘<em>More cheese with oregano</em>’ etc., each with their own cost()s. But we will also need to add in this layer, pizzas like ‘<em>More cheese with tomatoes and grilled chicken</em>’ to cater to people who might not want toppings but may want veggies and non-veg.</p>

<p>The third and fourth layers will have pizzas like ‘<em>Less cheese with Sriracha, onions and black olives</em>’ and ‘<em>More cheese with oregano, chilli flakes, onions, tomatoes, and smoked chicken</em>’ (sounds tasty, by the way!) respectively. If we count the number of subclasses in these two levels in the hierarchy, even after ignoring customers who may want to skip a layer, we get 31 x 30 = 930 and 3 x 930 = 2790 subclasses. So, with this approach:</p>

<ul>
  <li>The number of subclasses is simply overwhelming, and maintaining the code is going to be a mountain of a task for the developer team. Just writing the cost() methods in each of these classes to overwrite that of their parent class is a huge task. This scenario is called a <strong>Class Explosion.</strong></li>
  <li>Any modification to the price of any item will send shockwaves throughout the code, as the cost() methods of all the pizzas that contain this item will have to be modified again.</li>
  <li>Similarly, adding an item to a level, say Tomato Sauce to Toppings, is also going to be a big endeavour, as you’ll have to write a whole lot of classes and cost() methods.</li>
</ul>

<p><strong><em>Thus, this approach may be theoretically possible, but is extremely resource-intensive, not at all scalable and thus, NOT USEFUL AT ALL.</em></strong></p>

<h2 id="enter-decorators">ENTER DECORATORS.</h2>

<p>Decorators are a kind of wrapper for objects. They take the input, add functionality (if needed), pass it to the wrapped object, take output from the object, add functionality (if needed) and output to the environment.</p>

<p><img src="https://miro.medium.com/v2/resize:fit:875/1*CTXNQyElJfWmHsGc4qBjbA.png" alt="" /></p>

<p>The UML diagram for the Decorator Pattern (source: <em>Wikipedia</em>)</p>

<p>The ‘<em>Component</em>’ class is usually either an interface or an abstract class. ‘<em>ConcreteComponent</em>’ represents the instantiable class(es) which inherit(s) from ‘<em>Component</em>’.</p>

<p>Now we define a ‘<em>Decorator</em>’ class <strong>which also inherits from the ‘<em>Component</em>’.</strong> We pass the instance of ‘<em>ConcreteComponent</em>’ to be decorated to the Decorator. We want the user to feel as if they are working with the actual object and not the decorator (interacting with decorators instead of the expected object can complicate things from the user’s POV). This is why, in order to make the decorator <strong>transparent</strong>, the decorator inherits from the same class as the ‘<em>ConcreteComponent</em>’. Thus, a decorator both ‘is’ a ‘component’ (by virtue of having the same interface as the ‘<em>ConcreteComponent</em>’), and also ‘has’ a ‘component’ (the instance that is passed to it).</p>

<p>The decorator contains the same methods as the object (‘<em>ConcreteComponent’</em>) and these methods are overridden to forward the method calls to the method of the same name in the ‘<em>ConcreteComponent’</em> instance passed to it. The ‘<em>ConcreteDecorator</em>’ is a subclass of the decorator class which implements specific add-on functionalities by inheriting from the decorator class.</p>

<p>So, in essence, decorators are like <strong><em>transparent wrappers for objects</em></strong>, in that they add functionality but look and feel like the original object to the outside environment. Since we pass only a specific <em>instance</em> of a class to the decorator, other objects from the same class are not affected.</p>

<p><img src="https://miro.medium.com/v2/resize:fit:875/1*iCf6AIBPYUMtqW-RwN2Vlw.png" alt="" /></p>

<p>Another example: the idea for one is taken from <em>Design Patterns: Elements of Reusable Software by E. Gamma et al.</em></p>

<p>In the above example, we create a root class for handling Visual Displays which lets the user draw on the screen with the Draw() method, with a concrete implementation being a text document. Now in the decorator class, the Draw() method is overridden to call the Draw() method of the component that is passed to it. Then we implement this pattern into two ConcreteDecorators, a ScrollDecorator (which adds scroll bars) and a BorderDecorator (which adds a black border).</p>

<p>The other methods of <em>ConcreteDecorator</em> are not shown, but we see that the <em>ConcreteDecorator</em> Draw() calls its parent’s Draw() (in Python this can be done using super().Draw()) which in turn calls the component’s Draw(). Thus the user need not worry about using different method calls when the object is wrapped in a decorator, and can keep using it as the original TextDoc object. Thus the user can add/remove scrolls and borders whenever necessary.</p>

<h3 id="let-us-return-to-our-pizza-example">Let us return to our pizza example.</h3>

<p>Suppose a customer asks for a ‘<em>More cheese with oregano, onions, and smoked ham’.</em> You know that a More cheese pizza has a base cost of $10, and oregano, onions and smoked ham cost $1, $6, and $15 respectively. In the decorator approach, we define decorators of all the possible add-on items (Toppings, Veggies and Non-Veg) and have their cost() methods defined as</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">cost</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">component</span><span class="p">.</span><span class="n">cost</span><span class="p">()</span>
</code></pre></div></div>

<p><img src="https://miro.medium.com/v2/resize:fit:875/1*VMrczyGDGb1P9pdypR7uJg.png" alt="" /></p>

<p>Here, the user (the cashier) enters the pizza name, and it is processed as</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">pizza</span> <span class="o">=</span> <span class="n">smoked_ham_decorator</span><span class="p">(</span><span class="n">onions_decorator</span><span class="p">(</span><span class="n">oregano_decorator</span><span class="p">(</span><span class="n">more_cheese_object</span><span class="p">)))</span>
</code></pre></div></div>

<p>Now, the program calls the pizza.cost() method, which invokes the smoked_ham_decorator’s cost() method. Now, this decorator thinks that it contains a ‘<em>Pizza</em>’ (<em>ConcreteComponent</em>) object (because the onion_decorator, by design, has the <em>Component (Pizza)</em> interface, so it behaves as a <em>Pizza</em> object). So it calls the self.component.cost() method, which happens to be the onion_decorator.cost().</p>

<p>Similarly, onion_decorator.cost() is coded in the same way, and onion_decorator too thinks that it wraps a <em>Pizza</em> object when in reality, it is the oregano_decorator. These calls go on recursively, till we get to the more_cheese_object, which <strong>is</strong> in fact a <em>Pizza</em> object<em>,</em> and returns more_cheese_object.cost() = $10. Thus we get the price as:</p>

<p><strong>PRICE = $ 15 + ($ 6 + ($ 1 + ($ 10))) = $ 32.</strong></p>

<p>Thus, decorators help us:</p>

<ul>
  <li>Add a functionality to an object multiple times. If a customer wants two layers of onions on his Less Cheese pizza, we can just have it decorated as</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">onion_decorator</span><span class="p">(</span><span class="n">onion_decorator</span><span class="p">(</span><span class="n">less_cheese_object</span><span class="p">))</span>
</code></pre></div></div>

<ul>
  <li>Add the same functionality to multiple objects, adhering to the paradigm of keeping the code <strong>DRY</strong> (Don’t Repeat Yourself).</li>
  <li>Not have objects depend on parameters that they don’t need.</li>
</ul>

<p>Decorators offer an elegant solution to a number of problems in software design, while supporting flexibility, code reuse and division of labour within the code, making them, in my opinion, fundamental to object-oriented software design. Hopefully, after this introduction to decorators, you’ll understand what’s going on behind the scenes when you write an ‘@’!</p>

<p><em>(Migrated from Medium on 17 August 2026)</em></p>]]></content><author><name>insipidintegrator</name></author><category term="Programming" /><summary type="html"><![CDATA[Debunking misconceptions about decorators and presenting them in a simple-to-understand, lucid manner]]></summary></entry></feed>