<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged beginner</title>
<link>https://coderlegion.com/tag/beginner</link>
<description>Powered by Question2Answer</description>
<item>
<title>A Beginner’s Guide to Git and GitHub: From Installation to Your First Push</title>
<link>https://coderlegion.com/30826/a-beginners-guide-to-git-and-github-from-installation-to-your-first-push</link>
<description>&lt;p&gt;Starting my journey in &lt;strong&gt;Data Science, Analysis, and AI at LUXDevHQ&lt;/strong&gt; felt like learning a new language while trying to build a house. One of the most important tools I’ve discovered along the way is &lt;strong&gt;Version Control&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In this guide, I’ll walk you through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setting up Git Bash  &lt;/li&gt;
&lt;li&gt;Connecting Git to GitHub  &lt;/li&gt;
&lt;li&gt;Mastering essential &lt;strong&gt;push&lt;/strong&gt; and &lt;strong&gt;pull&lt;/strong&gt; commands  &lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-what-is-git-and-why-does-it-matter-&quot;&gt;1. What Is Git and Why Does It Matter?&lt;/h3&gt;
&lt;p&gt;Git is a &lt;strong&gt;Version Control System (VCS)&lt;/strong&gt;. Think of it as a &lt;em&gt;save-point system&lt;/em&gt; for your code.&lt;/p&gt;
&lt;h4 id=&quot;why-is-git-important-&quot;&gt;Why is Git important?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;⏪ Time Travel&lt;/strong&gt; – If you break your code, you can roll back to a version that worked.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🤝 Collaboration&lt;/strong&gt; – Multiple people can work on the same project without overwriting each other’s work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;🧪 Experimentation&lt;/strong&gt; – You can create &lt;em&gt;branches&lt;/em&gt; to try new features without affecting the main project.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-setting-up-your-environment&quot;&gt;2. Setting Up Your Environment&lt;/h3&gt;
&lt;h4 id=&quot;step-a-install-git-bash&quot;&gt;Step A: Install Git Bash&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a rel=&quot;nofollow&quot; href=&quot;https://git-scm.com&quot;&gt;Git&lt;/a&gt; and download Git for your OS (I used Windows).&lt;/li&gt;
&lt;li&gt;Run the installer.  &lt;blockquote&gt;&lt;p&gt;💡 &lt;em&gt;Pro tip:&lt;/em&gt; You can keep the default settings for most options.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;After installation, search for &lt;strong&gt;Git Bash&lt;/strong&gt; in your applications. It looks like a terminal window.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;step-b-configure-your-identity&quot;&gt;Step B: Configure Your Identity&lt;/h4&gt;
&lt;p&gt;To let GitHub know who is uploading code, configure your global Git settings:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git config --global user.name &quot;Your Name&quot;
git config --global user.email *Emails are not allowed*
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-secure-your-connection-setting-up-ssh-keys&quot;&gt;3. Secure Your Connection: Setting Up SSH Keys&lt;/h3&gt;
&lt;p&gt;Using SSH is the professional standard. It’s more secure and saves you from typing your password every time you push code.&lt;/p&gt;
&lt;h4 id=&quot;step-1-generate-your-ssh-key&quot;&gt;Step 1: Generate Your SSH Key&lt;/h4&gt;
&lt;p&gt;Open Git Bash and enter (replace with your GitHub email):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh-keygen -t ed25519 -C *Emails are not allowed*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;•File Location: Press Enter to use the default location.&lt;br&gt;
•Passphrase: As a beginner, I left this empty for convenience.&lt;/p&gt;
&lt;h4 id=&quot;step-2-add-key-to-the-ssh-agent&quot;&gt;Step 2: Add Key to the SSH Agent&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;eval &quot;$(ssh-agent -s)&quot;
ssh-add ~/.ssh/id_ed25519
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;step-3-add-the-public-key-to-github&quot;&gt;Step 3: Add the Public Key to GitHub&lt;/h4&gt;
&lt;p&gt;1.Copy the key: &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat ~/.ssh/id_ed25519.pub 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.Go to GitHub: Settings → SSH and GPG keys → New SSH Key.&lt;/p&gt;
&lt;p&gt;3.Give it a name (e.g., &quot;My Learning Laptop&quot;) and paste your key into the &quot;Key&quot; box.&lt;/p&gt;
&lt;h4 id=&quot;step-4-test-the-connection&quot;&gt;Step 4: Test the Connection&lt;/h4&gt;
&lt;p&gt;Run: &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ssh -T *Emails are not allowed*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Success Check! If you see &quot;Hi [YourUsername]! You've successfully authenticated&quot;, you are ready!&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-navigating-and-creating-your-project&quot;&gt;4. Navigating and Creating Your Project&lt;/h3&gt;
&lt;p&gt;Learning to navigate via Git Bash makes you much faster than using a mouse! Use these commands to create your first repository:&lt;br&gt;
•Check Location: &lt;strong&gt;pwd&lt;/strong&gt; (Print Working Directory).&lt;br&gt;
•Go to Desktop: &lt;strong&gt;cd Desktop&lt;/strong&gt;&lt;br&gt;
•Create Folder: &lt;strong&gt;mkdir my-first-repo&lt;/strong&gt;&lt;br&gt;
•Enter Folder: &lt;strong&gt;cd my-first-repo&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-tracking-changes-the-core-workflow-&quot;&gt;5. Tracking Changes (The Core Workflow)&lt;/h3&gt;
&lt;p&gt;Before sending code to GitHub, Git needs to &quot;track&quot; it locally. Run these inside your project folder:&lt;br&gt;
1.Initialize Git: &lt;strong&gt;git init&lt;/strong&gt; (Starts tracking the folder).&lt;br&gt;
2.Check Status: &lt;strong&gt;git status&lt;/strong&gt; (See what files Git notices).&lt;br&gt;
3.Add Files: &lt;strong&gt;git add .&lt;/strong&gt; (Stages all changes to be saved).&lt;br&gt;
4.Commit: &lt;strong&gt;git commit -m &quot;My first commit&quot;&lt;/strong&gt; (Creates the &quot;save point&quot;).&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;6-pushing-code-to-github&quot;&gt;6. Pushing Code to GitHub&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Pushing&lt;/strong&gt; sends your local save points to the cloud.&lt;/p&gt;
&lt;h4 id=&quot;step-a-create-the-repository-on-github-com&quot;&gt;Step A: Create the Repository on GitHub.com&lt;/h4&gt;
&lt;p&gt;1.Log into GitHub, click the + icon → New repository.&lt;br&gt;
2.Name it (e.g., my-first-project) and keep it Public.&lt;br&gt;
3.Important: Leave &quot;Add a README&quot; unchecked to avoid conflicts.&lt;br&gt;
4.Click Create repository.&lt;/p&gt;
&lt;h4 id=&quot;step-b-connect-and-push&quot;&gt;Step B: Connect and Push&lt;/h4&gt;
&lt;p&gt;On the GitHub setup page, click SSH and copy the URL. Then run these commands one by one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git remote add origin *Emails are not allowed*:your-username/repo-name.git
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;7-pulling-code-from-github&quot;&gt;7. Pulling Code from GitHub&lt;/h3&gt;
&lt;p&gt;If you work on a different computer, use Pull to download the latest updates from the cloud:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git pull origin main
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-resources-to-keep-learning&quot;&gt;📚 Resources to Keep Learning&lt;/h3&gt;
&lt;p&gt;•&lt;a rel=&quot;nofollow&quot; href=&quot;https://git-scm.com/doc&quot;&gt;Official Git Documentation&lt;/a&gt;&lt;br&gt;
•&lt;a rel=&quot;nofollow&quot; href=&quot;https://skills.github.com/&quot;&gt;GitHub Skills: Interactive Courses&lt;/a&gt;&lt;br&gt;
•&lt;a rel=&quot;nofollow&quot; href=&quot;https://learngitbranching.js.org/&quot;&gt;Visualizing Git Commands (Game)&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;conclusion-congratulations-you-ve-just-set-up-a-professional-dev-workflow-git-can-be-tricky-at-first-but-keep-practicing-and-it-will-become-second-nature-if-you-ran-into-any-issues-drop-a-comment-below-and-let-s-help-each-other-out-&quot;&gt;Conclusion: Congratulations! You've just set up a professional dev workflow. Git can be tricky at first, but keep practicing and it will become second nature. If you ran into any issues, drop a comment below and let's help each other out!&lt;/h3&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30826/a-beginners-guide-to-git-and-github-from-installation-to-your-first-push</guid>
<pubDate>Mon, 12 Oct 2026 16:20:10 +0000</pubDate>
</item>
<item>
<title>Understanding Backpropagation with micrograd — Principles, Intuition, and Pitfalls I Ran Into</title>
<link>https://coderlegion.com/22806/understanding-backpropagation-with-micrograd-principles-intuition-and-pitfalls-into</link>
<description>&lt;blockquote&gt;&lt;p&gt;I had heard about &lt;strong&gt;backpropagation&lt;/strong&gt; many times, but I never really understood how it actually worked. When someone asked me what backpropagation was, all I could say was, &quot;It's how neural networks learn… I guess?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;I'd seen the formulas, I knew the chain rule, but it always felt like there was a wall between me and true understanding.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;So I spent two days reading &lt;strong&gt;Karpathy&lt;/strong&gt;'s &lt;strong&gt;micrograd&lt;/strong&gt; project source code. It's honestly the best explanation of the core principles of neural networks I've ever come across!&lt;br&gt;
👉 &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/karpathy/micrograd&quot;&gt;https://github.com/karpathy/micrograd&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This post documents what I learned and how I understand it now.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-this-post&quot;&gt;Why This Post&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I'd watched plenty of YouTube videos explaining backpropagation, but most of them just said:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Backpropagation is repeatedly applying the chain rule.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's true, but for a beginner, it's basically saying nothing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I was used to frameworks where a single line — &lt;code&gt;loss.backward()&lt;/code&gt; — got the job done, with no idea what was actually happening under the hood.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-key-code-amp-what-it-does&quot;&gt;The Key Code &amp;amp; What It Does&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class Value:
    def __init__(self, data, _child = (), _op = &quot;&quot;, label = &quot;&quot;):
        self.data = data
        self._prev = set(_child)
        self._backward = lambda: None
        self.grad = 0.0
        self._op = _op
        self.label = label
    
    def __repr__(self):
        return f&quot;Value(data = {self.data})&quot;

    def __add__(self, other):
        other = other if isinstance(other, Value) else Value(other)
        out = Value(self.data + other.data, (self, other), &quot;+&quot;)

       def _backward():
            self.grad += out.grad * 1.0
            other.grad += out.grad * 1.0
        out._backward = _backward
        return out

     def backward(self):

        topo = []
        visited = set()
        def build_topo(v):
            if v not in visited:
                visited.add(v)
                for child in v._prev:
                    build_topo(child)
                topo.append(v)
        self.grad = 1.0
        build_topo(self)

        for node in reversed(topo):
            node._backward()

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;micrograd also defines &lt;code&gt;__mul__&lt;/code&gt;, &lt;code&gt;tanh&lt;/code&gt;, &lt;code&gt;__pow__&lt;/code&gt; and other methods — they all work the same way, each attaching a different &lt;code&gt;_backward&lt;/code&gt; note. So I'm only showing the core code here.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;&lt;p&gt;Try this:&lt;br&gt;
a = Value(1.0)&lt;br&gt;
b = Value(2.0)&lt;br&gt;
n = a + b&lt;br&gt;
L = n.tanh()&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You'll get this result:&lt;br&gt;
&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9064488572173869505&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;how-it-works&quot;&gt;How It Works&lt;/h3&gt;
&lt;p&gt;When you write &lt;code&gt;n = a + b&lt;/code&gt;, here's what happens:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A new &lt;code&gt;Value&lt;/code&gt; instance &lt;code&gt;n&lt;/code&gt; is created.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;_backward&lt;/code&gt; function is attached to &lt;code&gt;n._backward()&lt;/code&gt; but &lt;strong&gt;not executed yet&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;backward()&lt;/code&gt; is called, it traverses the graph in reverse topological order, executing each node's &lt;code&gt;_backward()&lt;/code&gt; one by one.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;things-you-should-know&quot;&gt;Things You Should Know&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;Chain Rule:&lt;br&gt;
&lt;code&gt;∂e/∂a = (∂e/∂c)(∂c/∂a) + (∂e/∂d)(∂d/∂a)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;At first I didn't accumulate gradients in &lt;code&gt;_backward()&lt;/code&gt; — just assigned them. That led to some serious bugs.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Imagine you write:&lt;br&gt;
a = Value(2.0)&lt;br&gt;
b = a + a&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What do you expect?&lt;br&gt;
&lt;strong&gt;a.grad = 2, b.grad = 1?&lt;/strong&gt; Or &lt;strong&gt;a.grad = 1, b.grad = 1?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you run it, you'll find &lt;code&gt;a.grad = 1&lt;/code&gt; — which is completely wrong!&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;    def __add__(self, other):
    other = other if isinstance(other, Value) else Value(other)
    out = Value(self.data + other.data, (self, other), &quot;+&quot;)
    def _backward():
        self.grad = out.grad * 1.0   # self = a, other = a;
        other.grad = out.grad * 1.0  # both set a.grad = 1
    out._backward = _backward
    return out
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;Here's another example:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Try this:&lt;br&gt;
a = Value(2.0)&lt;br&gt;
b = Value(3.0)&lt;br&gt;
c = a + b&lt;br&gt;
d = a &lt;em&gt; b&lt;br&gt;
e = c &lt;/em&gt; d&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What are &lt;code&gt;a.grad&lt;/code&gt; and &lt;code&gt;b.grad&lt;/code&gt; this time?&lt;br&gt;
&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12734637975006860424&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;strong&gt;Clearly, the gradients of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; got overwritten!&lt;/strong&gt;&lt;br&gt;
So &lt;strong&gt;you MUST accumulate in &lt;code&gt;_backward()&lt;/code&gt;!&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;my-confusion&quot;&gt;My Confusion&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;For a long time I couldn't understand what &lt;code&gt;def _backward()&lt;/code&gt; and &lt;code&gt;out._backward = _backward&lt;/code&gt; were really doing. Sounds silly, I know.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I kept wondering: when &lt;code&gt;Value c&lt;/code&gt; is created, &lt;code&gt;out.grad&lt;/code&gt; defaults to 0 — how can it possibly backpropagate to find &lt;code&gt;self.grad&lt;/code&gt; and &lt;code&gt;other.grad&lt;/code&gt;? (Of course, back then I thought &lt;code&gt;out._backward = _backward&lt;/code&gt; would immediately execute the &lt;code&gt;_backward&lt;/code&gt; function 😅)&lt;/p&gt;
&lt;p&gt;Now I finally get it:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;After creating a new &lt;code&gt;Value c&lt;/code&gt;, &lt;code&gt;c._backward&lt;/code&gt; just stores the &lt;code&gt;_backward&lt;/code&gt; function without running it. It only executes when &lt;code&gt;backward()&lt;/code&gt; is called, traversing in reverse topological order.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;It's a naive question that came from a naive assumption, but I hope it helps other developers who've been stuck on the same thing.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;a-thought-that-followed&quot;&gt;A Thought That Followed&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;Imagine this:&lt;br&gt;
a = Value(2.0)&lt;br&gt;
b = Value(3.0)&lt;br&gt;
c = Value(2.0)&lt;br&gt;
d = a + b&lt;br&gt;
e = c + d&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do &lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, and &lt;code&gt;c&lt;/code&gt; have their &lt;code&gt;_backward&lt;/code&gt; executed?&lt;/p&gt;
&lt;p&gt;Answer: All three have &lt;code&gt;_backward&lt;/code&gt; set to &lt;code&gt;lambda: None&lt;/code&gt; (an empty function). When backpropagation reaches them, nothing happens — their gradients have already been accumulated through the upstream path.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-i-gained&quot;&gt;What I Gained&lt;/h3&gt;
&lt;p&gt;After carefully reading through &lt;strong&gt;Karpathy&lt;/strong&gt;'s &lt;strong&gt;micrograd&lt;/strong&gt; source code, I was genuinely impressed. I'd never understood the core of &lt;strong&gt;backpropagation&lt;/strong&gt; so intuitively before. Here's what I took away:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I now understand the core mechanism of &lt;strong&gt;backpropagation&lt;/strong&gt; — &lt;code&gt;.backward()&lt;/code&gt; is no longer a black box to me.&lt;/li&gt;
&lt;li&gt;I finally &lt;strong&gt;truly understand&lt;/strong&gt; what &quot;backpropagation is just repeatedly applying the chain rule&quot; means.&lt;/li&gt;
&lt;li&gt;This has kicked off my deep dive into &lt;strong&gt;deep learning&lt;/strong&gt;, and now I can better compare &lt;strong&gt;micrograd&lt;/strong&gt; with &lt;strong&gt;PyTorch&lt;/strong&gt; and modern neural network frameworks.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;/h3&gt;
&lt;p&gt;Thanks for taking the time to read this. I wrote it right after going through the source code, so there may be mistakes in my understanding — corrections are very welcome.&lt;/p&gt;
&lt;p&gt;If you're also a beginner in &lt;strong&gt;deep learning&lt;/strong&gt;, feel free to reach out. I'd love to learn together with you.&lt;/p&gt;
&lt;p&gt;If you enjoyed this post, don't forget to like, bookmark, comment, and follow! I'll be sharing my learning journey in &lt;strong&gt;deep learning&lt;/strong&gt;, &lt;strong&gt;machine learning&lt;/strong&gt;, &lt;strong&gt;backend development&lt;/strong&gt;, and more from time to time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Check out my Dev.to&lt;/strong&gt;: &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/elysianx138&quot;&gt;https://dev.to/elysianx138&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;My GitHub will also track my learning progress&lt;/strong&gt;: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/elysianx138&quot;&gt;https://github.com/elysianx138&lt;/a&gt;  &lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22806/understanding-backpropagation-with-micrograd-principles-intuition-and-pitfalls-into</guid>
<pubDate>Thu, 16 Jul 2026 11:48:52 +0000</pubDate>
</item>
<item>
<title>Noughts, Crosses, and Questionable Decisions</title>
<link>https://coderlegion.com/22317/noughts-crosses-and-questionable-decisions</link>
<description>&lt;hr&gt;
&lt;p&gt;I made this Tic-Tac-Toe game when I was &lt;strong&gt;14&lt;/strong&gt; and still a beginner programmer. At the time, I did not know much about using advance functions, so the code is not the most efficient and has some repeated parts. I made it to strengthen my coding ability and practise using loops, lists, user input, and basic game logic. It may be simple, but every great programmer starts somewhere.&lt;/p&gt;
&lt;h3 id=&quot;the-good-stuff-&quot;&gt;&lt;strong&gt;The Good Stuff™&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Interactive two-player Tic-Tac-Toe gameplay&lt;/li&gt;
&lt;li&gt;Dynamic board updates after every move&lt;/li&gt;
&lt;li&gt;Comprehensive win detection across rows, columns, and diagonals&lt;/li&gt;
&lt;li&gt;Turn-based game logic&lt;/li&gt;
&lt;li&gt;Built using core Python language features&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-beginner-me-missed&quot;&gt;&lt;strong&gt;What Beginner Me Missed&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Reduce code duplication by refactoring repeated logic into reusable functions &lt;strong&gt;&lt;em&gt;&lt;code&gt; def  &lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Prevent players from selecting board positions that have already been occupied&lt;/li&gt;
&lt;li&gt;Provide clearer feedback when an invalid move is entered.&lt;/li&gt;
&lt;li&gt;Improve code organisation and maintainability through a more modular structure&lt;/li&gt;
&lt;li&gt;Add a replay option to allow multiple games without restarting the program&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
board = [ &quot; 1 &quot;, &quot; 2 &quot;, &quot; 3 &quot;, &quot; 4 &quot;, &quot; 5 &quot;, &quot; 6 &quot;, &quot; 7 &quot;, &quot; 8 &quot;, &quot; 9 &quot;]

line = &quot;\n------------------&quot;
straight_line = &quot;|&quot;

player_one = &quot;X&quot;
player_two = &quot;O&quot;
current_player = player_one
print(f&quot;{current_player}, it's your turn&quot;)

row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;

print(f&quot;\n{row_one}{line}{row_two}{line}{row_three}&quot;)
while True:
    play = int(input(f&quot;\n{current_player}, enter your move (1-9): &quot;))
    play -= 1
    if play == 0 :
        board[0] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 1 :
        board[1] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 2 :
        board[2] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 3 :
        board[3] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 4 :
        board[4] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 5 :
        board[5] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 6 :
        board[6] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 7 :
        board[7] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)
    elif play == 8 :
        board[8] = f&quot; {current_player} &quot;
        row_one =  f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two =  f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one , line , row_two , line, row_three)
        if board[0] == board[1] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[3] == board[4] == board[5]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[7] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[3] == board[6]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[1] == board[4] == board[7]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[2] == board[5] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] == board[4] == board[8]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[6] == board[4] == board[2]:
            print(f&quot;\n{current_player} wins!&quot;)
            break
        if board[0] != &quot; 1 &quot; and board[1] != &quot; 2 &quot; and board[2] != &quot; 3 &quot; and board[3] != &quot; 4 &quot; and board[4] != &quot; 5 &quot; and \
            board[5] != &quot; 6 &quot; and board[6] != &quot; 7 &quot; and board[7] != &quot; 8 &quot; and board[8] != &quot; 9 &quot;:
            print(&quot;\nIt's a tie!&quot;)
            break
        if current_player == player_one:
            current_player = player_two
            print(f&quot;\n{current_player} , it's your turn&quot;)
        else:
            current_player = player_one
            print(f&quot;\n{current_player} , it's your turn&quot;)

    else :
        print(&quot;\nEnter Valid Number&quot;)
        row_one = f&quot; {board[0]} {straight_line}  {board[1]} {straight_line} {board[2]} &quot;
        row_two = f&quot;\n {board[3]} {straight_line}  {board[4]} {straight_line} {board[5]} &quot;
        row_three = f&quot;\n {board[6]} {straight_line}  {board[7]} {straight_line} {board[8]} &quot;
        print(row_one, line, row_two, line, row_three)

&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22317/noughts-crosses-and-questionable-decisions</guid>
<pubDate>Sat, 11 Jul 2026 15:01:49 +0000</pubDate>
</item>
<item>
<title>What I Wish I'd Known About Binary Search Trees Before Interviews</title>
<link>https://coderlegion.com/18867/what-i-wish-id-known-about-binary-search-trees-before-interviews</link>
<description>&lt;p&gt;Three months of practicing binary search trees on paper. Search procedure memorised. Insertion procedure memorised. Three deletion cases memorised. Then came the onsite. The interviewer drew a tree on the whiteboard, asked for an insertion walkthrough, and the recall worked fine. Then she asked for a deletion of a node with two children, and the freeze lasted almost a full minute before the inorder successor steps came out without any real understanding of why they preserved the ordering. She let the explanation finish, then asked one followup: why does the inorder successor specifically work? There was no answer beyond &quot;because the textbook says so.&quot; That was the moment the gap became obvious. The months spent memorising procedures had skipped the part the interview was actually testing.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;What changed afterwards:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BST search, insert, and delete are not three procedures. They are the same recursive walk with three different terminal conditions.&lt;/li&gt;
&lt;li&gt;The two child deletion case is the one interviewers probe because it is the only case where the invariant has to be explained out loud.&lt;/li&gt;
&lt;li&gt;Memorising the inorder successor trick doesn't transfer. Being able to say why the inorder successor specifically works does.&lt;/li&gt;
&lt;li&gt;Once the invariant becomes the unit of memory, every operation that preserves it becomes derivable on the spot.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;where-the-approach-was-breaking&quot;&gt;Where the approach was breaking&lt;/h3&gt;
&lt;p&gt;What had been getting practiced wasn't the data structure. It was a list of procedures the invariant could have handed over for free.&lt;/p&gt;
&lt;p&gt;The recall pattern looked like this. Open a BST problem. Recognise it as a BST problem. Try to recall the right procedure for whatever the question asked. Search? Walk down comparing target to current. Insert? Same walk, create a leaf at the bottom. Delete? Three cases, pick the matching one, run the steps. The recall worked fine for problems that matched the textbook exactly. It fell apart the moment the problem deviated, because there was no deeper rule available to derive a new procedure from.&lt;/p&gt;
&lt;p&gt;The specific failure on that first interview was treating the two child deletion case as a separate procedure rather than a question about the invariant. The procedure said &quot;find the inorder successor, copy its value, delete the original successor.&quot; Those steps executed fine. What didn't execute was the reason behind them, which was the actual signal the interviewer was checking.&lt;/p&gt;
&lt;p&gt;The gap is small in concept and load bearing in practice. If you can recite the steps but can't explain why each one preserves the rule, you will lose the thread whenever the interview adds a constraint that doesn't appear in the textbook version. And interviews almost always add a constraint.&lt;/p&gt;
&lt;h3 id=&quot;what-started-working-differently&quot;&gt;What started working differently&lt;/h3&gt;
&lt;p&gt;After that interview, the practice rebuild was small in shape and large in effect. Instead of &quot;memorise the procedure, then run it,&quot; the new approach was &quot;start from the invariant, then derive what has to happen to preserve it.&quot; Same problems, same operations, completely different relationship to the material.&lt;/p&gt;
&lt;p&gt;The contrast looked like this:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Before (procedure first)                            &lt;/th&gt;&lt;th&gt;After (invariant first)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Memorise search as a walk down comparing values     &lt;/td&gt;&lt;td&gt;Start from &lt;code&gt;left &amp;lt; node &amp;lt; right&lt;/code&gt; and derive the walk as the consequence&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Memorise insert as &quot;find null pointer, create leaf&quot; &lt;/td&gt;&lt;td&gt;Notice that insert is the same walk, only the terminal action changes&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Memorise three deletion cases                       &lt;/td&gt;&lt;td&gt;Ask &quot;what value can sit in this slot without breaking the invariant?&quot;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Recall the inorder successor as a step              &lt;/td&gt;&lt;td&gt;Derive the inorder successor as the answer to the slot question&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Stall on novel problems                             &lt;/td&gt;&lt;td&gt;Answer novel problems by reasoning forward from the rule&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The shift was to remember fewer things, more carefully. There is exactly one rule for a BST: every node's left subtree contains only smaller values, every right subtree contains only larger values. Every operation either preserves the rule or is incorrect. That framing made the procedures fall out naturally, because the question &quot;what do I do here?&quot; reduced to &quot;what action keeps the rule intact?&quot;&lt;/p&gt;
&lt;h3 id=&quot;what-that-looked-like-on-the-next-problem&quot;&gt;What that looked like on the next problem&lt;/h3&gt;
&lt;p&gt;A month later came a phone screen at a different company. The interviewer gave a tree with &lt;code&gt;[8, 3, 10, 1, 6, 14]&lt;/code&gt; and asked for a search for &lt;code&gt;6&lt;/code&gt; and then an insertion of &lt;code&gt;7&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Search started at the root. &lt;code&gt;6 &amp;lt; 8&lt;/code&gt;, so go left to &lt;code&gt;3&lt;/code&gt;. Then &lt;code&gt;6 &amp;gt; 3&lt;/code&gt;, so go right to &lt;code&gt;6&lt;/code&gt;. Found it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def search(node, target):
    if node is None or node.value == target:
        return node
    if target &amp;lt; node.value:
        return search(node.left, target)
    return search(node.right, target)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then inserting &lt;code&gt;7&lt;/code&gt; was the same walk. From the root, &lt;code&gt;7 &amp;lt; 8&lt;/code&gt;, go left. Then &lt;code&gt;7 &amp;gt; 3&lt;/code&gt;, go right to &lt;code&gt;6&lt;/code&gt;. Then &lt;code&gt;7 &amp;gt; 6&lt;/code&gt;, go right again. Right pointer is null. Create node &lt;code&gt;7&lt;/code&gt; there.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def insert(node, value):
    if node is None:
        return Node(value)
    if value &amp;lt; node.value:
        node.left = insert(node.left, value)
    elif value &amp;gt; node.value:
        node.right = insert(node.right, value)
    return node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What was different this time was the framing said out loud after the code finished. Search and insert are the same recursive walk. Search stops when the value matches or the pointer is null. Insert stops at a null pointer and writes a new leaf there. The walk is what the invariant requires. The terminal action is the only thing that changes between operations. The interviewer asked a few more questions and then moved on. The framing was the part that mattered, not the code.&lt;/p&gt;
&lt;p&gt;The same shift made deletion easier too. Instead of three cases, the new mental model was one question: what value can sit in this slot without breaking &lt;code&gt;left &amp;lt; node &amp;lt; right&lt;/code&gt;? For a leaf, the answer is no value. Drop the pointer. For a one child node, the answer is the child's value, because the child's subtree already satisfies the invariant against the parent. For a two child node, the answer is the smallest value larger than the deleted node (the inorder successor), which is what the slot requires after deletion. Three procedures collapsed into three answers to the same question.&lt;/p&gt;
&lt;h3 id=&quot;why-this-works-the-invariant-doing-the-heavy-lifting-&quot;&gt;Why this works (the invariant doing the heavy lifting)&lt;/h3&gt;
&lt;p&gt;The reason the invariant first framing holds up under interview pressure has a name in learning science: near transfer versus far transfer. Memorising a procedure builds a near transfer skill. The procedure applies to problems that look exactly like the one that got practiced. It doesn't apply to problems that look slightly different, because the procedure is tied to the specific form of the original.&lt;/p&gt;
&lt;p&gt;Deriving a procedure from a rule builds a far transfer skill. The rule applies to any problem that respects the rule, regardless of how the form changes. The rule is what generalises. The procedure is what gets generated for the specific case.&lt;/p&gt;
&lt;p&gt;BSTs make this concrete because there is exactly one rule and there are dozens of variant problems that ask you to apply it. BST validation. Conversion to sorted array. Conversion to sorted doubly linked list. Range queries. Kth smallest element. Lowest common ancestor in a BST. BST iterator. All derivable from &quot;left subtree smaller, right subtree larger.&quot; None easy to memorise as individual procedures, because there are too many of them and they shade into each other.&lt;/p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.codeintuition.io/courses/binary-search-tree/-qJIiGUt7_snRlnBS-g_6&quot;&gt;inorder successor lesson&lt;/a&gt; walks the two child deletion case from the invariant down, which is the framing that most first practice resources skip. The procedure becomes the easy part once the question is framed as &quot;what value belongs in this slot?&quot;&lt;/p&gt;
&lt;h3 id=&quot;what-i-d-tell-someone-in-the-same-spot&quot;&gt;What I'd tell someone in the same spot&lt;/h3&gt;
&lt;p&gt;If your BST practice is at the point where the procedures feel memorised but the mock interviews aren't going well, the shift to make is to stop quizzing yourself on the steps and start quizzing yourself on the rule.&lt;/p&gt;
&lt;p&gt;A practice protocol that worked for the rebuild:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Before solving any BST problem, write the invariant at the top of the page. &lt;code&gt;left &amp;lt; node &amp;lt; right&lt;/code&gt; for every node, applied recursively to every subtree. Look at it for ten seconds.&lt;/li&gt;
&lt;li&gt;Read the problem and ask: what action does the invariant require here? Not &quot;what procedure do I run.&quot; What does the rule say has to happen.&lt;/li&gt;
&lt;li&gt;Trace one example by hand on paper, narrating each step as &quot;this preserves the rule because...&quot; If that sentence won't finish, what's running is a memorised procedure, not a derivation from the rule.&lt;/li&gt;
&lt;li&gt;Code it up. If the code falls out naturally from the narration, you have it. If a procedure shows up that you can't justify, stop and go back to step 2.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The protocol slows things down at first. Adding a thirty second pause to write the invariant and narrate the reasoning feels expensive under time pressure. The payoff is that the slow practice transfers. When the interview adds a constraint, the procedure that would have been recalled is wrong, but the rule still applies and the new procedure derives in real time.&lt;/p&gt;
&lt;p&gt;That gap, between solving a BST problem and recognising why an operation works, is the thing that pushed me to build Codeintuition. Watching engineers grind through hundreds of tree problems without the invariant first framing was the pattern that wouldn't stop showing up. The tree courses now lead with the rule and let the procedures fall out, which is the ordering that would have saved months on the first attempt.&lt;/p&gt;
&lt;p&gt;Originally posted on &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.codeintuition.io/blogs/binary-search-tree-explained&quot;&gt;my own blog&lt;/a&gt;, a slightly longer version with the inorder traversal proof and the balanced construction algorithm.&lt;/p&gt;
&lt;p&gt;What is a data structure that started making sense for you only after you stopped memorising the operations and started re-deriving them from the rule?&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/18867/what-i-wish-id-known-about-binary-search-trees-before-interviews</guid>
<pubDate>Mon, 25 May 2026 09:11:56 +0000</pubDate>
</item>
<item>
<title>Big O Notation: What I Wish I'd Known Before My First Interview</title>
<link>https://coderlegion.com/18747/big-o-notation-what-i-wish-id-known-before-my-first-interview</link>
<description>&lt;p&gt;The Big O table was memorised before the first onsite. Binary search logarithmic, merge sort linearithmic, hash insert constant amortised. All recitable. Then a senior engineer wrote a recursive function on the whiteboard, asked for an analysis, and almost a minute went by trying to match what was on the board to something on the cached table. The function was a naive recursive Fibonacci, seen before, implemented before. The freeze still happened, because nothing about the table told anyone how to count the recursive calls.&lt;/p&gt;
&lt;h4 id=&quot;what-i-figured-out-afterwards&quot;&gt;What I figured out afterwards&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;The table is the answer, not the method. Memorising it never builds the ability to derive complexity from code you haven't seen.&lt;/li&gt;
&lt;li&gt;The thing the table hides is the counting. How many times the dominant operation runs as a function of input size.&lt;/li&gt;
&lt;li&gt;Once four or five derivations have been traced by hand, the shape generalises. Unfamiliar code stops feeling opaque.&lt;/li&gt;
&lt;li&gt;Space complexity has the same derivation shape, plus the call stack that's easy to forget.&lt;/li&gt;
&lt;li&gt;The drill that actually builds the skill is deriving complexity on problems whose answer you don't already know.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;where-the-approach-was-breaking-1&quot;&gt;Where the approach was breaking&lt;/h3&gt;
&lt;p&gt;The Fibonacci moment exposed the gap. The function had been seen. The function had been implemented. What hadn't happened was counting what the recursion actually does.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def fib(n):
    if n &amp;lt; 2:
        return n
    return fib(n - 1) + fib(n - 2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The interviewer was patient. &quot;How many calls does &lt;code&gt;fib(5)&lt;/code&gt; make?&quot; The whiteboard got a tree. &lt;code&gt;fib(5)&lt;/code&gt; calls &lt;code&gt;fib(4)&lt;/code&gt; and &lt;code&gt;fib(3)&lt;/code&gt;. &lt;code&gt;fib(4)&lt;/code&gt; calls &lt;code&gt;fib(3)&lt;/code&gt; and &lt;code&gt;fib(2)&lt;/code&gt;. &lt;code&gt;fib(3)&lt;/code&gt; shows up twice. &lt;code&gt;fib(2)&lt;/code&gt; shows up three times. The tree grew faster than the page it was being drawn on. The answer wasn't in cached memory because no one had asked for the count before. The answer is &lt;code&gt;O(2ⁿ)&lt;/code&gt;, roughly, and the reason is that each call branches into two and the depth is about &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Big O had been treated as a label to attach after solving. The interview was treating it as a derivation to perform on unfamiliar code. Those are different skills, and the wrong one had been practiced.&lt;/p&gt;
&lt;h3 id=&quot;what-started-working-differently-1&quot;&gt;What started working differently&lt;/h3&gt;
&lt;p&gt;The fix wasn't reading more articles. It was changing the drill. The new prompt was &quot;given this code you haven't seen before, what's the complexity, and how would you justify it&quot; instead of &quot;what's the complexity of merge sort.&quot; Once the prompt changed, the way unfamiliar code reads changed with it.&lt;/p&gt;
&lt;p&gt;Here's the shape that worked, side by side with the old habit:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Then &lt;/th&gt;&lt;th&gt;Now&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Match the code to a memorised complexity. &lt;/td&gt;&lt;td&gt;Identify the dominant operation, the one that runs most.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Look up the answer when the match wasn't obvious. &lt;/td&gt;&lt;td&gt;Count how many times that operation runs, as a function of &lt;code&gt;n&lt;/code&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Move on once a label was attached. &lt;/td&gt;&lt;td&gt;Sum the work across levels (loops, recursion depth, branching factor).&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Forget about space until reminded. &lt;/td&gt;&lt;td&gt;Track space the same way: auxiliary memory plus the call stack.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The change is a habit, not a piece of knowledge. The Big O table doesn't get more correct over time. The way unfamiliar code gets read does.&lt;/p&gt;
&lt;h3 id=&quot;what-that-looked-like-on-the-next-problem-1&quot;&gt;What that looked like on the next problem&lt;/h3&gt;
&lt;p&gt;A few weeks after the Fibonacci interview, the same function came back out for re-derivation from scratch. No looking up the answer. Just the dominant operation and counting.&lt;/p&gt;
&lt;p&gt;The dominant operation in &lt;code&gt;fib(n)&lt;/code&gt; is the recursive call. &lt;code&gt;fib(n)&lt;/code&gt; calls &lt;code&gt;fib(n-1)&lt;/code&gt; and &lt;code&gt;fib(n-2)&lt;/code&gt;. Treat both as roughly &lt;code&gt;fib(n-1)&lt;/code&gt; for the upper bound. So the call count &lt;code&gt;T(n) ≈ 2 × T(n-1)&lt;/code&gt;. That recurrence solves to &lt;code&gt;T(n) = 2ⁿ&lt;/code&gt;. The depth of the tree is about &lt;code&gt;n&lt;/code&gt;. The branching factor is 2. Total work is roughly the number of nodes in a binary tree of depth &lt;code&gt;n&lt;/code&gt;, which is &lt;code&gt;2ⁿ&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That's why naive Fibonacci is unusably slow even at moderate &lt;code&gt;n&lt;/code&gt;. &lt;code&gt;fib(40)&lt;/code&gt; makes more than a billion calls.&lt;/p&gt;
&lt;p&gt;Adding memoisation changes the shape entirely:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def fib(n, memo={}):
    if n in memo:
        return memo[n]
    if n &amp;lt; 2:
        return n
    memo[n] = fib(n - 1, memo) + fib(n - 2, memo)
    return memo[n]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now each subproblem &lt;code&gt;fib(k)&lt;/code&gt; for &lt;code&gt;k&lt;/code&gt; from 0 to &lt;code&gt;n&lt;/code&gt; is computed exactly once. There are &lt;code&gt;n&lt;/code&gt; distinct subproblems. Each one does constant work after its two subcalls return. Total: &lt;code&gt;O(n)&lt;/code&gt; time, &lt;code&gt;O(n)&lt;/code&gt; space from the memo plus the call stack.&lt;/p&gt;
&lt;p&gt;The complexity went from &lt;code&gt;O(2ⁿ)&lt;/code&gt; to &lt;code&gt;O(n)&lt;/code&gt; because the structure of the work changed, and the derivation made that visible in a way the table never did. (For the longer walkthrough of how memoisation becomes the gateway to dynamic programming, &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.codeintuition.io/blogs/dynamic-programming-interview&quot;&gt;the DP interview blog&lt;/a&gt; covers the recurrence-to-table-to-bottom-up progression.)&lt;/p&gt;
&lt;h3 id=&quot;why-this-works-the-science-behind-it-&quot;&gt;Why this works (the science behind it)&lt;/h3&gt;
&lt;p&gt;The learning science term for the swapped drill is &lt;em&gt;elaborative interrogation&lt;/em&gt;. Asking yourself why each operation contributes the work it does, rather than accepting the labelled answer at face value. The literature on it is consistent: forcing yourself to construct the reason produces a more durable, more transferable understanding than reading the reason already constructed.&lt;/p&gt;
&lt;p&gt;The other piece is &lt;em&gt;near transfer versus far transfer&lt;/em&gt;. The old drill was near transfer practice (the same complexity question on the same code already memorised). The interview was a far transfer test (different code, same skill). Near transfer practice doesn't reliably move far transfer scores. Once that lands, the right drill picks itself: derive complexity on code you haven't seen.&lt;/p&gt;
&lt;h3 id=&quot;what-to-tell-someone-in-the-same-spot&quot;&gt;What to tell someone in the same spot&lt;/h3&gt;
&lt;p&gt;Three things, in the order they mattered.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Stop quizzing yourself on named algorithms.&lt;/strong&gt; &quot;What's the complexity of merge sort&quot; trains memory, not derivation. Quiz yourself on an unfamiliar function instead, and force yourself to count the dominant operation explicitly. If you have to count it out loud, that's the right intensity.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trace at least one recursive call tree by hand per week.&lt;/strong&gt; The first few feel slow. The fifth or sixth is where the shape generalises. Branching factor times depth gives nodes, nodes times work-per-node gives total work. The arithmetic is the same on every problem.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Track space the same way you track time.&lt;/strong&gt; Auxiliary memory plus call-stack frames. Most engineers in interviews get time right and space wrong, and the difference is purely habit.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Before this shift, a solution would read as &lt;em&gt;that looks fast&lt;/em&gt; and the analysis would stop there. After, the same solution reads as &lt;code&gt;O(n log n)&lt;/code&gt; because the divide step and the merge step can be pointed at independently. Adding a hash map to a nested loop visibly drops the complexity from quadratic to linear, with the derivation right there in the code. Unfamiliar code becomes analysable because the analysis is something you do, not something you recall.&lt;/p&gt;
&lt;p&gt;Originally posted on &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.codeintuition.io/blogs/big-o-notation-explained&quot;&gt;my own blog&lt;/a&gt;, with the amortised analysis derivation for hash-map resize and the space-complexity traps skipped over in this retrospective.&lt;/p&gt;
&lt;p&gt;What's a piece of complexity analysis that finally clicked for you only after deriving it by hand, where the textbook label had never really stuck?&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/18747/big-o-notation-what-i-wish-id-known-before-my-first-interview</guid>
<pubDate>Sat, 23 May 2026 11:29:05 +0000</pubDate>
</item>
<item>
<title>Bash exit codes 0-255: what they mean and how to write the handler</title>
<link>https://coderlegion.com/16902/bash-exit-codes-0-255-what-they-mean-and-how-to-write-the-handler</link>
<description>&lt;h3 id=&quot;-holds-the-exit-code-of-the-last-command-that-ran-you-ve-seen-it-you-ve-probably-checked-it-what-you-might-not-have-is-a-reliable-reference-for-what-each-value-actually-means-and-more-importantly-what-to-do-about-it-in-your-script-&quot;&gt;&lt;code&gt;$?&lt;/code&gt; holds the exit code of the last command that ran. You've seen it. You've probably checked it. What you might not have is a reliable reference for what each value actually means — and more importantly, what to &lt;em&gt;do&lt;/em&gt; about it in your script.&lt;/h3&gt;
&lt;h4 id=&quot;here-s-the-most-common-codes-with-the-detail-that-s-usually-missing-from-quick-reference-tables-&quot;&gt;Here's the most common codes with the detail that's usually missing from quick-reference tables.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;0 — Success&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;the-command-exited-cleanly-zero-is-the-only-value-that-means-success-everything-else-is-some-form-of-failure-or-interruption-&quot;&gt;The command exited cleanly. Zero is the only value that means success. Everything else is some form of failure or interruption.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;1 — General error&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;this-is-the-catch-all-a-lot-of-programs-use-1-to-signal-something-went-wrong-but-i-m-not-going-to-be-more-specific-when-you-see-1-you-need-to-look-at-the-command-s-own-output-or-error-messages-to-find-out-what-actually-failed-&quot;&gt;This is the catch-all. A lot of programs use 1 to signal &quot;something went wrong but I'm not going to be more specific.&quot; When you see 1, you need to look at the command's own output or error messages to find out what actually failed.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;2 — Misuse of shell built-in&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;you-called-a-bash-built-in-with-wrong-arguments-common-cause-if-var-with-a-missing-right-hand-operand-the-command-exits-2-when-the-syntax-is-wrong-&quot;&gt;You called a bash built-in with wrong arguments. Common cause: &lt;code&gt;if [ $var = ]&lt;/code&gt; with a missing right-hand operand. The &lt;code&gt;[&lt;/code&gt; command exits 2 when the syntax is wrong.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;126 — Command found, not executable&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;the-binary-exists-but-can-t-be-run-most-common-cause-missing-execute-permission-fix-chmod-x-yourscript-sh-worth-noting-this-is-different-from-127-the-system-found-the-file-it-just-can-t-execute-it-&quot;&gt;The binary exists but can't be run. Most common cause: missing execute permission. Fix: &lt;code&gt;chmod +x yourscript.sh&lt;/code&gt;. Worth noting: this is &lt;em&gt;different&lt;/em&gt; from 127. The system found the file — it just can't execute it.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;127 — Command not found&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;the-binary-doesn-t-exist-or-isn-t-in-path-most-common-causes-typo-in-command-name-package-not-installed-or-path-issue-in-cron-see-the-cron-job-post-above-when-you-see-127-in-a-cron-job-context-check-path-first-&quot;&gt;The binary doesn't exist or isn't in PATH. Most common causes: typo in command name, package not installed, or PATH issue in cron (see the cron job post above). When you see 127 in a cron job context, check PATH first.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;130 — Killed with Ctrl-C (SIGINT)&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;the-formula-is-128-signal-number-sigint-signal-2-128-2-130-if-your-script-sees-130-from-a-subprocess-someone-hit-ctrl-c-or-the-process-received-sigint-programmatically-&quot;&gt;The formula is 128 + signal number. SIGINT = signal 2. 128 + 2 = 130. If your script sees 130 from a subprocess, someone hit Ctrl-C (or the process received SIGINT programmatically).&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;137 — Killed with SIGKILL&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;128-9-sigkill-this-is-the-oom-killer-when-linux-runs-out-of-memory-and-needs-to-reclaim-it-fast-sigkill-is-what-it-uses-if-your-script-exits-137-unexpectedly-on-a-server-check-available-memory-free--h-and-dmesg-grep--i-kill-&quot;&gt;128 + 9 (SIGKILL). This is the OOM killer. When Linux runs out of memory and needs to reclaim it fast, SIGKILL is what it uses. If your script exits 137 unexpectedly on a server, check available memory — &lt;code&gt;free -h&lt;/code&gt; and &lt;code&gt;dmesg | grep -i kill&lt;/code&gt;.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;139 — Segmentation fault&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;the-process-tried-to-access-memory-it-wasn-t-allowed-to-access-in-a-bash-context-this-usually-means-a-compiled-binary-your-script-called-has-a-bug-you-re-not-going-to-fix-the-segfault-from-bash-but-you-can-detect-it-and-handle-it-cleanly-&quot;&gt;The process tried to access memory it wasn't allowed to access. In a bash context, this usually means a compiled binary your script called has a bug. You're not going to fix the segfault from bash — but you can detect it and handle it cleanly.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;143 — Killed with SIGTERM&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;128-15-sigterm-this-is-the-polite-kill-what-kill-pid-sends-by-default-and-what-systemd-sends-when-stopping-a-service-unlike-sigkill-sigterm-can-be-caught-and-handled-&quot;&gt;128 + 15 (SIGTERM). This is the polite kill — what &lt;code&gt;kill PID&lt;/code&gt; sends by default, and what systemd sends when stopping a service. Unlike SIGKILL, SIGTERM can be caught and handled.&lt;/h4&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;The error handler problem&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;knowing-what-a-code-means-is-step-one-writing-a-handler-that-does-something-useful-with-it-is-step-two-most-bash-error-handling-i-see-in-the-wild-looks-like-this-&quot;&gt;Knowing what a code means is step one. Writing a handler that does something useful with it is step two. Most bash error handling I see in the wild looks like this:&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;if [ $? -ne 0 ]; then
  echo &quot;error&quot;
  exit 1
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;which-logs-nothing-meaningful-and-loses-the-original-exit-code-a-better-pattern-&quot;&gt;Which logs nothing meaningful and loses the original exit code. A better pattern:&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;if [ $? -eq 127 ]; then
  echo &quot;ERROR: command not found — check PATH or installation&quot; &amp;gt;&amp;amp;2
  exit 127
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;log-to-stderr-preserve-the-original-exit-code-be-explicit-about-what-went-wrong-&quot;&gt;Log to stderr, preserve the original exit code, be explicit about what went wrong.&lt;/h3&gt;
&lt;hr&gt;
&lt;h3 id=&quot;free-tool-that-generates-these-handlers&quot;&gt;&lt;strong&gt;Free tool that generates these handlers&lt;/strong&gt;&lt;/h3&gt;
&lt;h4 id=&quot;i-built-bash-exit-code-lookup-https-bashsnippets-xyz-tools-bash-exit-code-lookup-html-1-to-remove-the-google-it-then-write-the-handler-by-hand-step-you-type-a-code-or-click-one-of-the-common-ones-pick-a-handler-style-if-else-block-case-statement-or-inline-fallback-and-copy-the-generated-handler-directly-into-your-script-&quot;&gt;I built [Bash Exit Code Lookup][(https://bashsnippets.xyz/tools/bash-exit-code-lookup.html)]&lt;a rel=&quot;nofollow&quot; href=&quot;https://bashsnippets.xyz/tools/bash-exit-code-lookup.html&quot;&gt;1&lt;/a&gt; to remove the &quot;Google it, then write the handler by hand&quot; step. You type a code (or click one of the common ones), pick a handler style — if/else block, case statement, or inline &lt;code&gt;||&lt;/code&gt; fallback — and copy the generated handler directly into your script.&lt;/h4&gt;
&lt;h4 id=&quot;all-codes-0-255-are-in-there-free-no-login-&quot;&gt;All codes 0-255 are in there. Free, no login.&lt;/h4&gt;
&lt;p&gt;→ &lt;a rel=&quot;nofollow&quot; href=&quot;https://bashsnippets.xyz/tools/bash-exit-code-lookup.html&quot;&gt;https://bashsnippets.xyz/tools/bash-exit-code-lookup.html&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/16902/bash-exit-codes-0-255-what-they-mean-and-how-to-write-the-handler</guid>
<pubDate>Wed, 06 May 2026 22:27:13 +0000</pubDate>
</item>
<item>
<title>The Ultimate Guide: Installing Ollama on Fedora 43</title>
<link>https://coderlegion.com/13729/the-ultimate-guide-installing-ollama-on-fedora-43</link>
<description>&lt;p&gt;Running large language models (LLMs) locally isn’t just for the privacy-obsessed anymore—it’s for anyone who wants a snappy, custom coding assistant without a monthly subscription. If you’re rocking Fedora 43, you’re already using one of the most cutting-edge distros out there.&lt;/p&gt;
&lt;p&gt;Here is how to get Ollama up and running with full NVIDIA acceleration and hook it into VS Code for a seamless dev experience.&lt;/p&gt;
&lt;p&gt;There’s something uniquely satisfying about seeing your GPU fans spin up because your local AI is thinking. Let’s get you there in eight steps.&lt;/p&gt;
&lt;h3 id=&quot;step-1-open-the-gates-rpm-fusion-&quot;&gt;Step 1: Open the Gates (RPM Fusion)&lt;/h3&gt;
&lt;p&gt;Fedora is known for its commitment to free, open-source software, which means the proprietary NVIDIA drivers aren't there by default. We need to add the RPM Fusion repositories to get the &quot;non-free&quot; goodies.&lt;/p&gt;
&lt;p&gt;Run this in your terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo dnf5 install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm 
sudo dnf5 install https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note: We’re using dnf5 here, which is the faster, shinier version of the package manager standard in Fedora 43.&lt;/p&gt;
&lt;h3 id=&quot;step-2-the-driver-dance&quot;&gt;Step 2: The Driver Dance&lt;/h3&gt;
&lt;p&gt;Now, we install the NVIDIA drivers and the CUDA toolkit. This is what allows Ollama to talk to your GPU instead of making your CPU do all the heavy lifting.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo dnf5 install akmod-nvidia xorg-x11-drv-nvidia-cuda
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A word of caution: Fedora moves fast. Sometimes, when the kernel updates, the NVIDIA modules need a moment to &quot;catch up&quot; (rebuild). If you update your system and things look wonky, it’s usually because the driver is still compiling in the background.&lt;/p&gt;
&lt;h3 id=&quot;step-3-the-classic-reboot&quot;&gt;Step 3: The Classic Reboot&lt;/h3&gt;
&lt;p&gt;You know the drill. For the kernel to start using those new NVIDIA drivers, you need a fresh start. sudo reboot&lt;/p&gt;
&lt;h3 id=&quot;step-4-the-moment-of-truth&quot;&gt;Step 4: The Moment of Truth&lt;/h3&gt;
&lt;p&gt;Once you’re back in, let’s make sure Fedora and your GPU are on speaking terms. Run this command,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nvidia-smi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you see a table showing your GPU name and VRAM usage, congratulations—you’ve passed the hardest part.&lt;/p&gt;
&lt;h3 id=&quot;step-5-installing-ollama&quot;&gt;Step 5: Installing Ollama&lt;/h3&gt;
&lt;p&gt;Ollama makes installation incredibly easy with a one-liner script. This script handles the heavy lifting: it downloads the binary, creates an ollama user/group, and sets up a systemd service so it starts automatically.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -fsSL https://ollama.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;step-6-verifying-the-gpu-link&quot;&gt;Step 6: Verifying the GPU Link&lt;/h3&gt;
&lt;p&gt;Just because Ollama is installed doesn't mean it’s using your GPU. It might be falling back to your CPU if it can't find the drivers. Let's check the logs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;journalctl -u ollama -b | grep &quot;NVIDIA&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’re looking for a line that confirms an NVIDIA GPU was detected. If you see it, you're golden.&lt;/p&gt;
&lt;h3 id=&quot;step-7-your-first-local-run&quot;&gt;Step 7: Your First Local Run&lt;/h3&gt;
&lt;p&gt;Let's test it with a lightweight, high-performance model. Qwen 2.5 Coder (0.5B version) is tiny but surprisingly &quot;smart&quot; for its size, making it perfect for a quick test.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ollama run qwen2.5-coder:0.5b
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once it downloads, you can chat with it directly in your terminal. Ask it to write a Python script; you'll be impressed by the speed.&lt;/p&gt;
&lt;h3 id=&quot;integrating-with-vs-code-the-continue-extension-&quot;&gt;Integrating with VS Code (The &quot;Continue&quot; Extension)&lt;/h3&gt;
&lt;p&gt;Running AI in a terminal is cool, but having it inside your IDE is where the real productivity happens. We’ll use the Continue extension, which is an open-source powerhouse for local AI.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install the Extension: Search for &quot;Continue&quot; in the VS Code Marketplace and install it.&lt;/li&gt;
&lt;li&gt;Configure Local Access: Open the Continue sidebar, click the gear icon (settings), and select your local config file.&lt;/li&gt;
&lt;li&gt;Edit the Config: Replace or add the following to your config.yaml (or config.json depending on your version) to point it toward your local Ollama instance:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;name: Local Config
version: 1.0.0
schema: v1
models:
  - name: Qwen2.5-Coder 0.5B
    provider: ollama
    model: qwen2.5-coder:0.5b
    apiBase: http://localhost:11434
    roles:
      - chat
      - edit
      - apply
      - autocomplete
      - embed
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;You now have a fully private, incredibly fast AI coding assistant running on your local hardware. No data leaving your machine, no latency issues, and total control.&lt;/p&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/13729/the-ultimate-guide-installing-ollama-on-fedora-43</guid>
<pubDate>Tue, 31 Mar 2026 04:49:25 +0000</pubDate>
</item>
<item>
<title>How to teach yourself coding without losing your mind</title>
<link>https://coderlegion.com/12337/how-to-teach-yourself-coding-without-losing-your-mind</link>
<description>&lt;p&gt;Teaching yourself how to code is easier than ever, but it can still feel overwhelming at the start. There are tutorials everywhere, endless opinions online, and about a thousand different “best” ways to learn. The people who actually stick with it usually do a few simple things really well. They focus on solid beginner friendly resources and ignore the noise.&lt;/p&gt;
&lt;p&gt;One of the best ways to learn coding on your own is through well made video lessons. Good videos let you watch someone write code from scratch, mess up, fix it, and explain what just happened. That alone can save hours of frustration. Instructors who have spent years teaching beginners know exactly where people get confused, so they slow down when it matters and explain things in plain language. The strongest video courses also push you to code along instead of just sitting back and watching.&lt;/p&gt;
&lt;p&gt;Books still matter more than people think. A good programming book gives you structure and depth that videos sometimes skip. Authors who have taught beginners for a long time tend to write like they are sitting next to you, not lecturing from a podium. They explain why things work, not just what to type. When you get stuck or forget something, a solid book becomes the place you go back to again and again.&lt;/p&gt;
&lt;p&gt;The real magic happens when you use both videos and books together. Videos help you get comfortable and see the big picture. Books help everything click and stick. A lot of successful learners watch a lesson, try it themselves, then read about the same topic to reinforce it. That back and forth makes learning feel more natural and a lot less stressful.&lt;/p&gt;
&lt;p&gt;It also pays to learn from people with real teaching experience. Someone who has guided beginners for years knows how to pace lessons and avoid unnecessary complexity. You can usually spot these instructors by long running courses, well reviewed books, and students who actually go on to build things.&lt;/p&gt;
&lt;p&gt;Above all, consistency wins. Coding a little every day with good resources beats cramming once a week. Stick with trusted instructors, practice often, and be patient with yourself. That is how beginners turn into confident programmers.&lt;/p&gt;
&lt;p&gt;Troy Tuckett is an author with 20 years of experience helping beginners become great coders.&lt;a rel=&quot;nofollow&quot; href=&quot;https://beacons.ai/troytuckett&quot;&gt;More information here:&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12337/how-to-teach-yourself-coding-without-losing-your-mind</guid>
<pubDate>Tue, 03 Mar 2026 02:47:54 +0000</pubDate>
</item>
<item>
<title>CPU - Traditional Version (2)</title>
<link>https://coderlegion.com/10965/cpu-traditional-version-2</link>
<description>&lt;p&gt;Continue on how CPU works. As we already know that CPU only knows numbers and calculate number. And So a natural question is &quot;&lt;em&gt;how CPU loops and create condition if the CPU only know how to calculate?&lt;/em&gt;&quot;.&lt;/p&gt;
&lt;p&gt;To put it simply, CPUs have special instructions that allow them to jump between instructions. We can &quot;emulate&quot; loop and condition, for example in my CPU simulation i have this instruction called &lt;code&gt;JZ&lt;/code&gt; (jump if zero). As the name suggests, it jumps to another instruction if a certain value is zero.&lt;/p&gt;
&lt;p&gt;example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-asm&quot;&gt;LOAD A, 1
LOAD B, 1

CMP A, B
JZ exit
STOREM A, 0 ; store value register A to memory
exit:

HALT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, a question appears: &quot;&lt;em&gt;what value does JZ actually check?&lt;/em&gt;&quot; we know that &lt;code&gt;exit&lt;/code&gt; is just a label on which line it's referring to, not a value. So how does &lt;code&gt;JZ&lt;/code&gt; know when to jump, and This is where branching flags come in.&lt;/p&gt;
&lt;p&gt;Before &lt;code&gt;JZ&lt;/code&gt; instruction, there's called &lt;code&gt;CMP&lt;/code&gt; instruction As the name implies is a compare instruction, like example above it compare register A value and register B value.&lt;/p&gt;
&lt;p&gt;During this comparison, the CPU updates special internal flags. The most important ones are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Z (Zero flag): true if the result is zero&lt;/li&gt;
&lt;li&gt;N (Negative flag): true if the result is negative&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my simulation, I explicitly store these flags. In real CPUs, these flags are stored in a special register (often called a status register or flags register).&lt;/p&gt;
&lt;p&gt;After the calculation for &lt;code&gt;CMP&lt;/code&gt; complete the CPU updates the Z and N flags. And when &lt;code&gt;JZ&lt;/code&gt; instruction start they will look at Z flag. And if the the Z flag is true (or 1), execute the jump to chosen location.&lt;/p&gt;
&lt;p&gt;Same as Loop, like example below&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-asm&quot;&gt;LOAD A, 4
LOAD B, 1
LOAD C, 1

loop:
SUB A, B ; substract A with B
CMP A, C
JZ exit ; if A == C
JMP loop ; not equal than repeat
exit:

HALT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you see can see above this instruction is the simplest loop where if A is equal to B exit loop. &lt;/p&gt;
&lt;p&gt;To create the loop, we need two jump instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JZ&lt;/code&gt; for the conditional jump.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JMP&lt;/code&gt; for the unconditional jump back to the loop. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the &lt;code&gt;JZ&lt;/code&gt; condition is not satisfied, the CPU moves to the next instruction, which is &lt;code&gt;JMP&lt;/code&gt;. Since &lt;code&gt;JMP&lt;/code&gt; has no condition, the CPU will always follow it.&lt;/p&gt;
&lt;p&gt;In my simulation, the code for &lt;code&gt;CMP&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;// get value from register and substract
int temp = reg.r[inst.operandA] - reg.r[inst.operandB];
// check if zero or negative 
flag.zero = (temp == 0);
flag.negative = (temp &amp;lt; 0);
programCounter++;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;The important rule is that the &lt;code&gt;CMP&lt;/code&gt; instruction should not store any new value in registers or memory. It only updates the flags.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Of course there is other instruction other than &lt;code&gt;JZ&lt;/code&gt; such as: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;JG&lt;/code&gt; (jump if greater),&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JL&lt;/code&gt; (jump if less),&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JNZ&lt;/code&gt; (jump if not zero),&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and many others, depending on the CPU design.&lt;/p&gt;
&lt;p&gt;So when you see a code like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;int valueA = 2
int valueB = 3

if (valueA == valueB) {
    // do stuff
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;in CPU it basically try to subtract &lt;code&gt;valueA&lt;/code&gt; and &lt;code&gt;valueB&lt;/code&gt; and if zero condition fulfill (ignoring compiler optimizations).&lt;/p&gt;
&lt;p&gt;And from this branching flags alone, there are many possibility you can create in here because from my experience no matter the fancy code is inside are just bunch of condition and loop. &lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10965/cpu-traditional-version-2</guid>
<pubDate>Tue, 03 Feb 2026 09:10:33 +0000</pubDate>
</item>
<item>
<title>CPU - Traditional Version</title>
<link>https://coderlegion.com/10661/cpu-traditional-version</link>
<description>&lt;p&gt;I've been building quite a few projects and one of them is this CPU Simulation. I've been in the web world for 4 years, but i still did not understand what CPU is. So in the past week i start to build a small project CPU-Simulation that follow the behavior in the CPU.&lt;/p&gt;
&lt;p&gt;Why the sudden interest in CPUs? Curiosity. There was a trigger after reading an article on how CPU work and they the work is quite simple, that got me thinking &quot;hey, i can build that&quot;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Note: This is the article &lt;a rel=&quot;nofollow&quot; href=&quot;https://homepage.cs.uri.edu/faculty/wolfe/book/Readings/Reading04.htm&quot;&gt;CPU&lt;/a&gt; and this one &lt;a rel=&quot;nofollow&quot; href=&quot;https://cpu.land/the-basics&quot;&gt;CPU&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, in CPU they have two important component called Control Unit and ALU (Arithmetic Logic Unit). At a high level, they follow a simple idea often described as “fetch and execute.” In more detail, the cycle looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Control Unit&lt;br&gt;
This Control Unit responsible for fetch instruction from memory and decode the instruction into something ALU can read. by decoding means they translate the instruction into control signal that the ALU can act on.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Arithmetic Logic Unit (ALU)&lt;br&gt;
ALU is responsible for execution the instruction that producing a result and storing the result in register or memory.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So to put it simple it more like fetch -&amp;gt; decode -&amp;gt; execute -&amp;gt; store -&amp;gt; next. That's the whole cycle, the cycle repeat until all instruction is complete.&lt;/p&gt;
&lt;p&gt;From this it's tell me that, the computer work in a simple and predictable manner. The CPU does not care what program it given, it only cares whether an instruction is valid and whether it can be executed.&lt;/p&gt;
&lt;p&gt;So i did manage to build the simulation using java, and it can be improve later. Here some code &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/IkhwanAL/cpu-simulation&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I use web browser to interact with the cpu, the cpu have 4 register index and 100 bytes of memory. But right now i only create small portion on how CPU work.&lt;/p&gt;
&lt;p&gt;Here gist code &lt;a rel=&quot;nofollow&quot; href=&quot;https://gist.github.com/IkhwanAL/cfecd57953df84835d71a61f8524d9bf&quot;&gt;CU &amp;amp; ALU&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see from github code the CU or Control Unit have it's own class. The class contain few important part and there is fetch the program convert to stream and decode it, to something that Simulation ALU can read.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  private int resolveInstruction(Operand op) {

    // Convert to Number
    if (op instanceof LabelRef label) {
      Integer addr = labels.get(label.name());

      if (addr == null) {
        throw new IllegalStateException(&quot;Unknow Label :&quot; + label.name());
      }

      return addr;
    }

    // Convert to Number
    if (op instanceof HexCode hx) {
      return Integer.decode(hx.value());
    }

    // Convert to Number
    if (op instanceof Immediate imm) {
      return imm.value();
    }

    // Convert to Number
    if (op instanceof RegisterCode rc) {
      return parseRegister(rc.value());
    }

    return 0;
  }

  private Instruction resolver(RawInstruction ins) {
    var instruction = new Instruction();
    instruction.opcode = ins.opcode;
    switch (ins.opcode) {
      case HALT:
        break;
      case JMP:
        instruction.dest = resolveInstruction(ins.dest);
        break;
      case STOREM:
      case LOADM:
        instruction.dest = resolveInstruction(ins.dest);
        instruction.src = resolveInstruction(ins.src);
        break;
      case LOAD:
        instruction.dest = resolveInstruction(ins.dest);
        instruction.src = resolveInstruction(ins.src);
        break;
      case CMP:
      case ADD:
        instruction.dest = resolveInstruction(ins.dest);
        instruction.src = resolveInstruction(ins.src);
        break;
      case JZ:
        instruction.dest = resolveInstruction(ins.dest);
        break;
      case null:
      default:
        break;
    }

    return instruction;
  }

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can see from function called &lt;code&gt;resolver&lt;/code&gt; it convert every value into number. Because CPU does not talk other than number.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;  void execute(Register reg, Memory mem, ArrayList&amp;lt;Instruction&amp;gt; program) {
    if (programCounter &amp;lt; 0 || programCounter &amp;gt;= program.size()) {
      halted = true;
      fault = CpuFault.INVALID_PC;
      return;
    }

    Instruction inst = program.get(programCounter);

    switch (inst.opcode) {
      case LOAD:
      case STOREM:
      case LOADM:
      case ADD: // register to register
        this.store(inst, reg, mem);
        break;
      case CMP:
        int temp = reg.r[inst.dest] - reg.r[inst.src];
        flag.zero = (temp == 0);
        flag.negative = (temp &amp;lt; 0);
        programCounter++;
        break;
      case JMP:
        programCounter = inst.dest - 1;
        break;
      case JZ:
        if (flag.zero) {
          programCounter = inst.dest - 1;
        } else {
          programCounter++;
        }
        break;
      case HALT:
        halted = true;
        break;
      case null:
      default:
        fault = CpuFault.ILLEGAL_INSTRUCTION;
        halted = true;
    }
  }

  private void store(Instruction inst, Register reg, Memory mem) {
    switch (inst.opcode) {
      case LOADM:
        if (inst.src &amp;gt; mem.ram.length) {
          halted = true;
          fault = CpuFault.INVALID_MEM;
          break;
        }
        reg.r[inst.dest] = mem.ram[inst.src];
        programCounter++;
        break;
      case STOREM:
        if (inst.src &amp;gt; mem.ram.length) {
          halted = true;
          fault = CpuFault.INVALID_MEM;
          break;
        }
        mem.ram[inst.src] = reg.r[inst.dest];
        programCounter++;
        break;
      case ADD:
        int res = reg.r[inst.dest] + reg.r[inst.src];
        reg.r[inst.dest] = res;
        flag.zero = (res == 0);
        flag.negative = (res &amp;lt; 0);
        programCounter++;
        break;
      case LOAD:
        reg.r[inst.dest] = inst.src;
        programCounter++;
        break;
      default:
        break;
    }
  }

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And above code block is an important function in ALU Class, which contain execute function where it take the decoded instruction from Control Unit Class and execute it. And of course i add an error handler, the error handler in CPU are quite similar to most program, if there some illegal instruction or incorrect instruction they halted the program from execute. If you ever use a tool like &lt;code&gt;sudo&lt;/code&gt; or other linux command it's the same, if it's error stop the program.&lt;/p&gt;
&lt;p&gt;And other interesting part is the label tag like &lt;code&gt;loop:&lt;/code&gt; or &lt;code&gt;exit:&lt;/code&gt;. That label are just for parser to remember what line are they referring to. For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-asm&quot;&gt;LOAD A, 1
LOAD B, 1

loop:
ADD A, B
CMP A, 7
JZ exit
JMP loop

exit:
HALT
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;above instruction are a simple instruction for loop if value reach zero stop the loop. Equivalent with:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int A = 1
while (A != 7) {
    A += 1
}
return

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If i swap the &lt;code&gt;JZ exit&lt;/code&gt; with &lt;code&gt;JMP loop&lt;/code&gt; it can cause infinite loop. &lt;/p&gt;
&lt;p&gt;There are many more modern concepts in CPU design, but for now, I think a traditional CPU model is enough to understand the fundamentals.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/10661/cpu-traditional-version</guid>
<pubDate>Thu, 29 Jan 2026 05:57:40 +0000</pubDate>
</item>
<item>
<title>How I Discovered I Love Tech as a 26-Year-Old Sous Chef</title>
<link>https://coderlegion.com/3818/how-i-discovered-i-love-tech-as-a-26-year-old-sous-chef</link>
<description>&lt;p&gt;&quot;&lt;em&gt;At 8 PM, I was plating the second-to-last course of a wine dinner for 70 guests. At 3 AM, I was spinning up virtual machines and tearing apart old laptops.&lt;/em&gt;&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Intro&lt;/strong&gt;&lt;br&gt;
I’ve been cooking for as long as I can remember. When real life hit, I jumped straight into the kitchen — and almost never looked back. I tried a few other jobs here and there, but nothing ever really stuck. They paid the bills, sure, but they didn’t interest me.&lt;/p&gt;
&lt;p&gt;Cooking, though? I had the skills. I could make decent money doing it, and I loved it — so dealing with the chaos and the long hours felt worth it.&lt;/p&gt;
&lt;p&gt;But somewhere in the middle of all that, something shifted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Shift&lt;/strong&gt;&lt;br&gt;
I’d had a few conversations about IT over the years. My father-in-law teaches it and manages one of the server rooms at Promedica Hospital. Naturally, he likes to talk shop. The chats were insightful, but I never thought it was something for me.&lt;/p&gt;
&lt;p&gt;By then, I’d built a few gaming PCs for myself, friends, and family. Tinkering was fun. Researching? Even more fun. But that’s where it stopped.&lt;/p&gt;
&lt;p&gt;I used to think anything beyond basic setup — like OS knowledge or software deep-dives — was for hardcore enthusiasts. Then I started fixing Windows blue screens and got intrigued.&lt;/p&gt;
&lt;p&gt;“Why the hell are we even getting BSODs when we barely use our rigs for anything but games?”&lt;/p&gt;
&lt;p&gt;While researching those issues, Linux videos started popping up in my feed. I’d heard the name before, but didn’t know what it was. Curiosity kicked in. I figured I’d dip my toes in a little.&lt;/p&gt;
&lt;p&gt;I was wrong. I fell straight down the rabbit hole — and didn’t mind at all.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Curiosity Peaks&lt;/strong&gt;&lt;br&gt;
At this point, my curiosity was boiling. I wanted to try these tools, break things, fix them, and see what this world was all about.&lt;/p&gt;
&lt;p&gt;It started with my wife’s old Lenovo Ideapad. That thing hadn’t booted in years. The last time it did, it took 12 minutes just to reach the login screen — so we tossed it in a tote and forgot it existed.&lt;/p&gt;
&lt;p&gt;I swapped the HDD for an SSD, threw on Linux Mint, and... BAM.&lt;/p&gt;
&lt;p&gt;It worked. Like, actually worked. It booted to the desktop in 25 seconds. Buttery smooth and snappy compared to before.&lt;/p&gt;
&lt;p&gt;“Wait, I made this run again? Okay... terminal, here I come.”&lt;/p&gt;
&lt;p&gt;Mint didn’t last long. It was solid, don’t get me wrong, but I realized I was craving more. The dopamine hit. I needed to understand how this stuff worked, not just click around.&lt;/p&gt;
&lt;p&gt;My First Server&lt;br&gt;
So I hopped online, did more research, and pulled the trigger on a Dell Optiplex 7040 with an I7 6700 CPU 16GB RAM and a 128GB internal SSD.&lt;/p&gt;
&lt;p&gt;To this day im not sure if i could have done better, after the computer showed up not posting properly I got a partial refund from the seller before diving into it to see what was wrong. Replaced the Ram first, and it booted right up!&lt;/p&gt;
&lt;p&gt;$25 spent TOTAL! On what was going to be the foundation of my learning getting started in this journey.&lt;/p&gt;
&lt;p&gt;I threw a few parts in I had around and ended up with these specs:&lt;br&gt;
Dell Optiplex 7040:&lt;/p&gt;
&lt;p&gt;i7 6700 Cpu&lt;br&gt;
32 GB RAM&lt;br&gt;
128 GB m.2 SSD&lt;br&gt;
2 x 1 TB HDDs&lt;br&gt;
Operating System: Windows 10 Pro switched to ProxmoxVE&lt;br&gt;
Enter Proxmox&lt;br&gt;
Proxmox was an absolute blessing. It’s a full-blown virtualization platform that let me spin up Linux distros and operating systems like candy. No need to dual-boot or nuke my daily driver — I could just run whatever I wanted, whenever I wanted.&lt;/p&gt;
&lt;p&gt;So what did I do? I downloaded all the things.&lt;/p&gt;
&lt;p&gt;Ubuntu, Mint, Fedora, Kali... I didn’t even care if I used them for more than a few minutes — I just wanted to see them all, boot them all, and feel them all.&lt;/p&gt;
&lt;p&gt;At this point I was still a total newbie, but Proxmox made it stupid easy. It wasn’t long before I started seeing what other people were using Proxmox for.&lt;/p&gt;
&lt;p&gt;That’s when I really started playing:&lt;/p&gt;
&lt;p&gt;✅ OpenMediaVault VM → My own little NAS!&lt;/p&gt;
&lt;p&gt;✅ Pi-hole VM → Hosted my own ad blocker!&lt;/p&gt;
&lt;p&gt;And man, that was fun.&lt;/p&gt;
&lt;p&gt;But after a while... I noticed something.&lt;/p&gt;
&lt;p&gt;I wasn’t really learning how things worked. I was installing powerful tools, sure, but it felt like I was just following steps — like learning how to use apps more than actually understanding the systems underneath.&lt;/p&gt;
&lt;p&gt;So I shifted focus.&lt;/p&gt;
&lt;p&gt;I didn’t just want to run cool stuff.&lt;br&gt;
I wanted to know what made it all tick.&lt;/p&gt;
&lt;p&gt;Que montage of hours of researching linux and coding, setting up environments and learning how they work, using the terminal for everything i could until i became comfortable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where I Am Now&lt;/strong&gt;&lt;br&gt;
Today, I’m still cooking full-time — long hours, late nights — but something’s changed.&lt;br&gt;
When I clock out, I don’t shut down. I shift gears.&lt;/p&gt;
&lt;p&gt;My daily driver is a full Linux rig now — no dual boot, no fallback, just me and Nobara (a Fedora-based distro), handling everything from gaming to system tweaks to writing code. I’ve got my terminal customized, dotfiles synced, Starship prompt glowing — and I finally feel like my setup is mine.&lt;/p&gt;
&lt;p&gt;I’ve also got a second laptop running Fedora Workstation, built specifically for coding. Clean, focused, distraction-free. Python, VSCode, and a growing list of projects that are teaching me how things really work under the hood. Every new function, class, or tool I learn gets saved, tested, and turned into something real.&lt;/p&gt;
&lt;p&gt;And that old OptiPlex I snagged for $25?&lt;br&gt;
Yeah, I’m still using it — but now it’s running Fedora Server and acting as my self-hosted AI playground. I’ve got Ollama set up, playing with local models, using Docker to manage containers, and testing new tools that feel like straight-up magic. It’s wild how far I’ve come from just wanting to “see what Linux looks like.”&lt;/p&gt;
&lt;p&gt;This isn’t just curiosity anymore — it’s becoming craft.&lt;br&gt;
And I’m still just getting started.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
I'm not trying to sell you a bootcamp or tell you I’ve made it. As much as I hope I can make something out of this, I don't have a timeline. I’m still in the kitchen. Still debugging things I broke. Still learning how to code, how to build, how to think like an engineer.&lt;/p&gt;
&lt;p&gt;But now I feel like I belong in this space. What I've learned I've learned forever.&lt;/p&gt;
&lt;p&gt;I used to think tech was locked behind a degree or a job title — it’s not.&lt;br&gt;
It's built by people like me. People like you.&lt;br&gt;
People who stay up way too late fixing things just to see if they can.&lt;/p&gt;
&lt;p&gt;So if you’ve been curious, start. Break your laptop. Fix it. Google everything.&lt;br&gt;
Spin up your own weird little server.&lt;br&gt;
Customize your terminal until it feels like home.&lt;br&gt;
Build something nobody asked you to build — and keep going.&lt;/p&gt;
&lt;p&gt;There’s no finish line.&lt;br&gt;
Just more to learn — and that’s the best part.&lt;/p&gt;
&lt;p&gt; I'm a full-time sous chef chasing down a second passion in tech.&lt;/p&gt;
&lt;p&gt;Currently learning Linux, Python, and AI self-hosting — one late night at a time.&lt;/p&gt;
&lt;p&gt;Let’s connect — I’d love to hear your story too.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/3818/how-i-discovered-i-love-tech-as-a-26-year-old-sous-chef</guid>
<pubDate>Tue, 08 Jul 2025 07:22:52 +0000</pubDate>
</item>
<item>
<title>Learn All Seaborn Graphs in One Blog (With Code + Output)</title>
<link>https://coderlegion.com/3468/learn-all-seaborn-graphs-in-one-blog-with-code-output</link>
<description>&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;/h3&gt;
&lt;p&gt;Have you ever looked at beautiful graphs in data science projects and wondered how do I create them myself? If yes, you're not alone and Seaborn is the perfect tool to help you get started.&lt;/p&gt;
&lt;p&gt;Seaborn is a powerful Python library built over Matplotlib that makes it easier to create more informative, cleaner, and visually appealing statistical graphs. Whether you're presenting insights from a dataset, analyzing sales data, or visualizing customer behavior, Seaborn does it all with just a few lines of simple code.&lt;/p&gt;
&lt;p&gt;In this easy-to-learn blog, I will walk you through all the important Seaborn charts with code, visuals, and when and where to use these graphs. By the end, you’ll be able to create stunning plots that make your data come alive.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-your-environment&quot;&gt;Setting Up Your Environment&lt;/h3&gt;
&lt;p&gt;Before we dive into the graphs, let’s set up our environment:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Install seaborn
pip install seaborn
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, import the necessary libraries:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import seaborn as sns
import matplotlib.pyplot as plt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Loading the dataset:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# View available datasets
sns.get_dataset_names()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This piece of code will provide you with a list of all the datasets present.Some of the datasets present are iris,tips,penguins etc.&lt;/p&gt;
&lt;p&gt;We’ll use the tips dataset, which contains information about restaurant tips.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Load the dataset
df = sns.load_dataset('tips')

# View the first few rows
df.head()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This dataset includes features like total bill amount, tip amount, and customer info like sex, smoker, day, time, size, etc.&lt;/p&gt;
&lt;h3 id=&quot;types-of-plots-in-seaborn&quot;&gt;Types of Plots in Seaborn&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mcdt048rw201btckyaam.png&quot; alt=&quot;Types of plots&quot;&gt;&lt;/p&gt;
&lt;p&gt;After going through all these graphs, you'll be ready to make clean and stylish graphs in Seaborn.&lt;/p&gt;
&lt;h3 id=&quot;function-level-vs-axes-level-interface&quot;&gt;Function-Level vs. Axes-Level Interface&lt;/h3&gt;
&lt;p&gt;The two primary plotting interfaces offered by Seaborn are Function-level and Axes-level.Although both are useful for efficiently visualizing data but their structure and degree of control vary.&lt;br&gt;
Example:Lets say we have to  plot a scatterplot so if you want to do it using:&lt;br&gt;
Function-level interface: You simply use a generic function like sns.relplot() and specify the type of the plot using the kind parameter.This instructs Seaborn to use the relational plot function to produce a scatter plot&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.relplot(data=tips, x='total_bill', y='tip', kind='scatter')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Axes-level interface: In this instance, you use the plotting function's name, sns.scatterplot(), to call it directly.This increases your control and makes it possible to integrate with the figure/axis objects in Matplotlib.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.scatterplot(data=tips, x=&quot;total_bill&quot;, y=&quot;tip&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hence the function-level approach is quicker and simpler. Seaborn takes care of setting up the figure and axes, so you don't have to worry about it. Simply call a single function, such as relplot(), and use the kind parameter to specify the type of plot you want. This approach is excellent for beginners or for rapidly exploring your data.&lt;br&gt;
You have more control with the axes-level approach. Before calling the particular Seaborn function, such as scatterplot() or boxplot(), you first create the figure and axes using Matplotlib. Although it requires a little more effort, this is very helpful when you want to alter the layout and design or create multiple plots in a single figure.&lt;br&gt;
So, if you want something quick and simple, use the function-level interface. But if you need more flexibility and want to create detailed or customized plots, the axes-level method is better.&lt;br&gt;
Now that we’ve understood how Seaborn’s interfaces work, let’s explore some of the most commonly used plots. These will help you visualize different types of data — from comparisons to distributions and relationships.&lt;/p&gt;
&lt;h3 id=&quot;1-relational-plots&quot;&gt;1. Relational Plots&lt;/h3&gt;
&lt;p&gt; It is used in Seaborn  to visualize relationships between two variables i.e. it is used for Bivariate Analysis.The plots under this section are scatter plot and lineplot.&lt;/p&gt;
&lt;h4 id=&quot;a-i-scatter-plot&quot;&gt;a.(i) Scatter Plot&lt;/h4&gt;
&lt;p&gt;It is used to visualize the relationship between two numerical variables.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.scatterplot(data=tips, x='total_bill', y='tip', hue='sex', style='time', size='size')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdk49v8m22f1hqn4xqpd.png&quot; alt=&quot;Scatterplot axes-level&quot;&gt;&lt;/p&gt;
&lt;p&gt;This axes level scatter plot code contains-&lt;br&gt;
data=tips – We specify the dataset we are gonna be using.&lt;br&gt;
x='total_bill' – The values on the x-axis represent the total bill.&lt;br&gt;
y='tip' – The values on the y-axis represent the tip amount.&lt;br&gt;
hue='sex' – Points are colored based on the gender (male/female) of the customer.&lt;br&gt;
style='time' – The shape of each point depends on whether it was lunch or dinner.&lt;br&gt;
size='size' – The size of every point represents the number of individuals at the table.&lt;/p&gt;
&lt;h4 id=&quot;-ii-scatter-plot-function-level-&quot;&gt;(ii) Scatter Plot (Function-level)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.relplot(data=tips, x='total_bill', y='tip', kind='scatter', hue='sex', style='time', size='size')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;br&gt;
&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n3vbj6l2rro31douohnp.png&quot; alt=&quot;Scatterplot function-level&quot;&gt;&lt;/p&gt;
&lt;p&gt;If you notice the difference between these two graphs the function level gives us a kind of a rectangle shaped graph whereas in axes level is square shaped and the details of the graph have shifted to the right.The code is the same just you mention the type of plot and in the kind property you give the name of the graph.You have more control in axes level graphs and hence we will be continuing with it.&lt;/p&gt;
&lt;h4 id=&quot;b-line-plot&quot;&gt;b. Line Plot&lt;/h4&gt;
&lt;p&gt;A line plot is employed in illustrating the relationship between two variables, particularly when one variable signifies a sequence such as time, order, or continuous values. It is used in Trend Analysis,Comparisons,Patterns to identify growth, decline, spikes, or seasonality in data and for Smooth Transitions.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.lineplot(data=tips, x=&quot;size&quot;, y=&quot;total_bill&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cw3bjzf0myrxdw0h8an4.png&quot; alt=&quot;Lineplot&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;2-distribution-plots&quot;&gt;2. Distribution Plots&lt;/h3&gt;
&lt;p&gt;A distribution plot allows you to visualize how your data is distributed. It displays the frequency of values as a histogram, and sometimes includes a smoothed curve to indicate overall shape. This is helpful for identifying patterns, such as whether your data is normally shaped or skewed.The plots under this section are histplot,kdeplot and rugplot.&lt;/p&gt;
&lt;h4 id=&quot;a-hist-plot&quot;&gt;a. Hist Plot&lt;/h4&gt;
&lt;p&gt;Shows the distribution of a single numeric variable.Useful for understanding how values are spread out.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.histplot(data=tips, x=&quot;total_bill&quot;, bins=10)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5iyy8yjcs42mya2znt2x.png&quot; alt=&quot;Histplot&quot;&gt;&lt;br&gt;
This piece of code employs Seaborn's histplot() to plot a histogram of the distribution of the total_bill column of the tips dataset.&lt;br&gt;
 Data=tips indicates which dataset to use&lt;br&gt;
 x=&quot;total_bill&quot; indicates the column you would like to graph on the x-axis. &lt;/p&gt;
&lt;p&gt;The bins=10 argument indicates that the total bill values will be split into 10 ranges (or bins), and the graph will indicate how many entries are in each range. It serves to enlighten you as to how restaurant bills are distributed — whether most of them are small, high, or somewhere in between.&lt;/p&gt;
&lt;h4 id=&quot;b-kde-plot&quot;&gt;b. KDE Plot&lt;/h4&gt;
&lt;p&gt;A KDE plot draws a smooth curve to show how your data is spread out. It’s like a smoother version of a histogram and helps you see the overall shape or pattern in the data more clearly.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.kdeplot(data=tips, x=&quot;total_bill&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;br&gt;
&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1krj7mntrmiapuxuhu5.png&quot; alt=&quot;kdeplot&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;c-ecdf-plot&quot;&gt;c. ECDF Plot&lt;/h4&gt;
&lt;p&gt;An ECDF plot shows how the data accumulates over values. It helps you understand what proportion of values are less than or equal to a certain amount. It is  useful for spotting medians, percentiles, and spread.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.ecdfplot(data=tips, x=&quot;total_bill&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zcxhl27zeh2rkhu87wgr.png&quot; alt=&quot;ecdfplot&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;3-categorical-plots&quot;&gt;3. Categorical Plots&lt;/h3&gt;
&lt;p&gt;They are used when you want to compare values that fall into distinct categories, such as gender, day of week, or product category. These plots show how data is binned together and what each bin does. Seaborn makes it really easy to plot categories like bar plots, box plots, violin plots, and more with functions like catplot(). These are especially useful when working with survey data, customer segments, or anything that falls into distinct groups.The types of plots in this category are barplot,boxplot,violinplot,countplot and swarmplot.&lt;/p&gt;
&lt;h4 id=&quot;a-bar-plot&quot;&gt;a. Bar Plot&lt;/h4&gt;
&lt;p&gt;They are used to show average (or other statistics) of a numerical value across categories.You must give both x and y values (category and numeric data).It calculates and plots the mean of the y values for each category in x.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.barplot(data=tips, x='day', y='total_bill')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5t5r8zbupus6aq8n226p.png&quot; alt=&quot;Barplot&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;b-count-plot&quot;&gt;b. Count Plot&lt;/h4&gt;
&lt;p&gt;It is used to count how many times each category appears in your data.You only need to give the x (or y) value — just the category.It’s like a bar chart of value counts (similar to value_counts() in pandas).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.countplot(data=tips, x='day')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7s024hd4pjbyry5m7ae3.png&quot; alt=&quot;Countplot&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;c-box-plot&quot;&gt;c. Box Plot&lt;/h4&gt;
&lt;p&gt;A box plot summarizes the distribution of a numeric variable using five values: minimum, lower quartile (25%), median (50%), upper quartile (75%), and maximum. It also highlights outliers — data points that are unusually high or low.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.boxplot(data=tips, x='day', y='total_bill')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0joe4u386rte22zhafvz.png&quot; alt=&quot;Boxplot&quot;&gt;&lt;/p&gt;
&lt;p&gt;x='day', y='total_bill': For each day, Seaborn shows how the total bills are distributed.&lt;br&gt;
You can clearly see the median line inside the box, the box itself (middle 50% of data), and points outside (outliers).&lt;br&gt;
It’s a powerful tool to detect variation and inconsistency in your data.&lt;/p&gt;
&lt;h4 id=&quot;d-violin-plot&quot;&gt;d. Violin Plot&lt;/h4&gt;
&lt;p&gt;The violin plot builds on the box plot and adds a KDE (Kernel Density Estimate) on both sides to show the distribution shape of the data.While a box plot shows the summary, a violin plot shows where the data is concentrated.Each “violin” shows the density of data — wider sections mean more data points. You also get a central line and mini box inside that shows quartiles like a box plot.Great when you want both summary and distribution together.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.violinplot(data=tips, x='day', y='total_bill')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vzwha34rj6rzs6kex7pn.png&quot; alt=&quot;Violinplot&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;e-swarm-plot&quot;&gt;e. Swarm Plot&lt;/h4&gt;
&lt;p&gt;A swarm plot is like a smarter strip plot ,it adjusts the positions of points so that they don’t overlap and all are visible.It shows each data point clearly, while also giving a good sense of density (how many points are close together) and variation.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.swarmplot(data=tips, x='day', y='total_bill')
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yuqmllq3ohfw7sgo7psa.png&quot; alt=&quot;Swarmplot&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;4-matrix-plots&quot;&gt;4. Matrix Plots&lt;/h3&gt;
&lt;p&gt;Matrix plot is a chart for visualizing relationships between two numerical variables or showing how multiple variables relate to each other across matrix/grid layout.These diagrams are especially beneficial for Correlation analysis and Pairwise relationships.This type consist of heatmap and clustermap.&lt;/p&gt;
&lt;h4 id=&quot;a-heatmap&quot;&gt;a. Heatmap&lt;/h4&gt;
&lt;p&gt;-The heatmap derives its name from the concept that it is an affinity based fusion of a correlation matrix and the original visibility data. Each cell of the matrix is the pairing of two variables. Darker/lighter hues correspond to higher/low strength of association.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;corr = tips.corr(numeric_only=True)
sns.heatmap(corr, annot=True, cmap='coolwarm')
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbg6umyyoqxy1ardtv8c.png&quot; alt=&quot;Heatmap&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;b-clustermap&quot;&gt;b. Clustermap&lt;/h4&gt;
&lt;p&gt;A clustermap is similar to a heatmap, but in addition, it uses clustering algorithms (such as hierarchical clustering) to cluster together similar variables.It reorders rows and columns so that highly correlated variables are positioned close to one another.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;corr = tips.corr(numeric_only=True)
sns.clustermap(corr, annot=True, cmap='viridis', figsize=(6, 4))
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xuie6wm1xsni17us1jxk.png&quot; alt=&quot;Clustermap&quot;&gt;&lt;/p&gt;
&lt;p&gt;Variables that are more correlated (such as total_bill and tip) will be clustered closer on the axes. It helps you identify patterns and automatically arrange your data visually.&lt;br&gt;
sns.clustermap(corr, annot=True, cmap='viridis'): Works just like a heatmap but adds dendrograms (tree diagrams) to show clustering.&lt;/p&gt;
&lt;p&gt;The color bar still shows the correlation values.&lt;/p&gt;
&lt;p&gt;Great when your dataset has many variables.&lt;br&gt;
figsize=(6, 4) makes the figure 6 inches wide and 4 inches tall.&lt;/p&gt;
&lt;h3 id=&quot;5-multiplots&quot;&gt;5. MultiPlots&lt;/h3&gt;
&lt;p&gt;Plotting several charts in a single figure or layout is known as a multiplot in data visualization. This is very helpful in  situations when you wish to compare various visualizations side by side,The same data is being examined from several angles and for dashboards or reports.&lt;/p&gt;
&lt;h4 id=&quot;a-facetgrid&quot;&gt;a. FacetGrid&lt;/h4&gt;
&lt;p&gt;The Seaborn library includes the FacetGrid class which helps you display data through multiple plot grids. Through its functionality you can generate multiple plots that organize data according to category levels which reveals variable interactions and condition-based variations.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;g = sns.FacetGrid(tips, col=&quot;sex&quot;, row=&quot;time&quot;)
g.map(sns.scatterplot, &quot;total_bill&quot;, &quot;tip&quot;)
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mh83fnwk9wjsn4lugo2o.png&quot; alt=&quot;Facetgrid&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;b-catplot&quot;&gt;b. Catplot&lt;/h4&gt;
&lt;p&gt;It is a higher-level function built on FacetGrid that lets you create categorical plots in grids quickly.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.catplot(data=tips, x=&quot;day&quot;, y=&quot;total_bill&quot;, kind=&quot;box&quot;, col=&quot;sex&quot;)
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6a3oy80z1826jwmvdtfx.png&quot; alt=&quot;Catplot&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;c-pairplot&quot;&gt;c. Pairplot&lt;/h4&gt;
&lt;p&gt;It creates a matrix of scatter plots for all combinations of numerical variables. It's not a FacetGrid but still shows multiple plots in one figure.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sns.pairplot(tips, hue=&quot;sex&quot;, height=2, aspect=1)
plt.show()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pie2n1x0gsvp9bqahhd.png&quot; alt=&quot;Pairplot&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Thanks so much for stopping by and reading this blog! I hope it gave you a good and straightforward introduction to Seaborn and how to employ its various types of plots and I have only made graphs using axes level you can visit my github repo to explore function level too.&lt;/p&gt;
&lt;p&gt;If you're brand new to data visualization or want to enhance your skills, I’m happy you came along for the ride! If you liked this, please do share it, and look out for more beginner-friendly guides like this and if you have any doubts feel free to message me.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;View the complete code on GitHub&lt;/strong&gt;: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Aaryan-Lunis&quot;&gt;github.com/Aaryan-Lunis&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Happy plotting! &lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/3468/learn-all-seaborn-graphs-in-one-blog-with-code-output</guid>
<pubDate>Tue, 24 Jun 2025 19:00:45 +0000</pubDate>
</item>
</channel>
</rss>