<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ visualization - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ visualization - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 27 May 2026 16:21:51 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/visualization/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Learn Git through Gamification – A Visual Guide to Key Version Control Concepts ]]>
                </title>
                <description>
                    <![CDATA[ Git has many concepts and commands that you’ll need to understand before you feel confident using it. Some of these concepts may sound trivial, especially to someone who has worked with Git before. But like most Git and coding concepts, even the “sim... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-git-through-gamification/</link>
                <guid isPermaLink="false">67c1cfa78df3594301bc3fef</guid>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gamification  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ version control ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jacob Stopak ]]>
                </dc:creator>
                <pubDate>Sun, 02 Mar 2025 06:00:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1740686401633/ffd9ac3c-668a-47bf-b2ba-f7cee14e74a8.webp" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Git has many concepts and commands that you’ll need to understand before you feel confident using it. Some of these concepts may sound trivial, especially to someone who has worked with Git before. But like most Git and coding concepts, even the “simple” ones tend to be abstract.</p>
<p>The three concepts that stand out to me as the most fundamental for being able to effectively work with Git at a basic level are:</p>
<ol>
<li><p>The <strong>working directory</strong></p>
</li>
<li><p>The <strong>staging area</strong></p>
</li>
<li><p>The <strong>commit history</strong></p>
</li>
</ol>
<p>In this article, we’ll take a new approach to representing these three concepts: by <em>visualizing them in an immersive, 3D game world!</em></p>
<p>I’ll provide a tangible, visual representation of these key Git concepts which are almost always described in an abstract and confusing way. I hope that this will make them much more intuitive for you to grasp.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-visualize-your-working-directory">Visualize your Working Directory</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-demystify-your-staging-area">Demystify your Staging Area</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-literally-walk-through-your-commit-history">Literally Walk through your Commit History</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-try-it-yourself">Try it Yourself</a></p>
</li>
</ol>
<h2 id="heading-visualize-your-working-directory">Visualize your Working Directory</h2>
<p>What does your brain picture when you think of the “working directory”? I assume it’s something like a folder structure starting at the project root, containing the code files and subfolders that make up the project.</p>
<p>While that is a fair description of the working directory, it is a bit hard to imagine and misses the segmentation that Git applies to your project. Although the current state of your entire project, folder structure, and code files do reside in the working directory, Git doesn’t really need to do much about that unless certain <em>changes</em> are detected in those files.</p>
<p>Git detects and reports changes to the working directory with the <a target="_blank" href="https://initialcommit.com/blog/git-status">Git status command</a>, which shows output like this:</p>
<pre><code class="lang-bash">Jack@RAPTOR ~/my-project (main)&gt; git status
On branch main
Your branch is up to date with <span class="hljs-string">'origin/main'</span>.

Changes not staged <span class="hljs-keyword">for</span> commit:
  (use <span class="hljs-string">"git add &lt;file&gt;..."</span> to update what will be committed)
  (use <span class="hljs-string">"git restore &lt;file&gt;..."</span> to discard changes <span class="hljs-keyword">in</span> working directory)
        modified:   main.py
        modified:   settings.py

Untracked files:
  (use <span class="hljs-string">"git add &lt;file&gt;..."</span> to include <span class="hljs-keyword">in</span> what will be committed)
        one.py
        three.py
        two.py

no changes added to commit (use <span class="hljs-string">"git add"</span> and/or <span class="hljs-string">"git commit -a"</span>)
</code></pre>
<p>The two relevant sections here are:</p>
<ol>
<li><p><strong>Changes not staged for commit:</strong> Lists existing files tracked by Git which currently contain code changes. In the example above, we see two “modified files”: <code>main.py</code> and <code>settings.py</code>.</p>
</li>
<li><p><strong>Untracked files:</strong> Lists new files in your project that Git doesn’t know about yet. In the example above, we see three new, untracked files: <code>one.py</code>, <code>two.py</code>, and <code>three.py</code>.</p>
</li>
</ol>
<p>When it comes to understanding Git, thinking of the working directory as the changes Git sees in these two sections – <strong>Untracked files</strong> and <strong>Modified files</strong> – is quite helpful.</p>
<p>But the <code>git status</code> command reports these details in the terminal in a purely text-based way, which doesn’t do newer Git users any favors when it comes to wrapping their heads around Git.</p>
<p>Some Git GUI’s do a better job with this (they do provide a safer point-and-click interface, after all), but in my experience, none of them make things <em>obvious at a glance</em>.</p>
<p>Instead, imagine that as a new Git user, you saw this:</p>
<p><a target="_blank" href="https://devlands.com"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740587730262/375bef09-b8b8-43e3-a18c-5b1e589b6097.png" alt="Image captured from Devlands, the gamified Git interface and tutorial, showing the untracked files and modified files sections of the working directory wall" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<p>A nice big wall with clearly delineated sections for <strong>Untracked files</strong> and <strong>Modified files</strong>. Files corresponding to each section are represented as blocks on the wall within that section, clearly labelled with their filename.</p>
<p>More specifically, the blocks representing files <code>one.py</code>, <code>two.py</code>, and <code>three.py</code> are all sitting neatly in the <strong>Untracked files</strong> section, and the blocks representing the files <code>main.py</code> and <code>settings.py</code> are in the <strong>Modified files</strong> section.</p>
<p>This makes it abundantly clear to even a total novice that Git is interpreting these files differently and categorizing them in a logical way. It takes the abstract Git concept of the “working directory” and transforms it into a form that almost anyone can wrap their heads around at a glance.</p>
<p>But something is missing here. Let’s say you run the command <code>git add one.py</code>. This stages the untracked file <code>one.py</code> to be included in the next commit. What happens to the block labelled <code>one.py</code> on the wall?</p>
<h2 id="heading-demystify-your-staging-area">Demystify your Staging Area</h2>
<p>To answer that, let’s move on to the mysterious <a target="_blank" href="https://initialcommit.com/blog/git-add">Git “staging area”</a>. But first, where exactly IS the staging area?</p>
<p>Well, technically any staged file changes are still just sitting in the working directory, which makes things a bit confusing.</p>
<p>Here is how Git reports this in the terminal:</p>
<pre><code class="lang-bash">Jack@RAPTOR ~/D/git-worlds (main)&gt; git status
On branch main
Your branch is up to date with <span class="hljs-string">'origin/main'</span>.

Changes to be committed:
  (use <span class="hljs-string">"git restore --staged &lt;file&gt;..."</span> to unstage)
        new file:   one.py
</code></pre>
<p>As you can see from Git’s output, it now includes the section <strong>Changes to be committed</strong>, which includes the file <code>one.py</code> that was staged with the <code>git add</code> command.</p>
<p>But this is still a bit unclear. Are the staged file changes in <code>one.py</code> still a part of the working directory? Or does Git store them elsewhere?</p>
<p>Well, the answer is… BOTH:</p>
<p><a target="_blank" href="https://devlands.com"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740592262850/dc65c06d-0ec6-4de6-bbe9-53307d523e68.png" alt="Image captured from Devlands, the gamified Git interface and tutorial, adding the staged files section onto the working directory wall" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<p>Here you can see that we zoomed out a bit from the previous image, to reveal a third section of the wall labeled <strong>Staged files</strong>.</p>
<p>Since we ran the command <code>git add one.py</code>, you can see that the corresponding block representing the <code>one.py</code> file moved from the Untracked files column to the Staged files column.</p>
<p>This conveys quite clearly that a file sitting in the staging area is still a part of the working directory (because it is a part of the overall wall), while also being segmented into its own designated space.</p>
<p>From a technical perspective, Git’s staging area is just a file named <strong>index</strong> which lives in the <code>.git/</code> folder. Git builds up the code changes specified by the <code>git add</code> command in this file, which is used as the source for those changes the next time the <code>git commit</code> command is run.</p>
<p>But from a workflow perspective, representing the staging area as a section on the “working directory wall” as in the image above makes things more intuitive to understand.</p>
<p>Next, let’s explore how we might visualize things once the staged changes are turned into a new Git commit and become a part of the active branch.</p>
<h2 id="heading-literally-walk-through-your-commit-history">Literally Walk through your Commit History</h2>
<p>What does your mind’s eye see when you think of Git’s “commit history”?</p>
<p>Well, the prettiest way Git does it in the terminal is by using the <a target="_blank" href="https://initialcommit.com/blog/git-log">Git log command</a>, such as <code>git log --graph --all</code>, which provides output like:</p>
<pre><code class="lang-bash">* commit 88085cff3e2d7657f26eb6479b308526df7d2bba (HEAD -&gt; dev, origin/dev)
| Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| Date:   Tue Apr 23 20:31:24 2024 -0700
|
|     Fix <span class="hljs-built_in">command</span> as title clip, ellipses and arrow length <span class="hljs-keyword">in</span> rebase subcommand
|
|     Signed-off-by: Jacob Stopak &lt;jacob@initialcommit.io&gt;
|
*   commit e264605ea26a808c34d4dc2fbc6dad65a8e28c5f
|\  Merge: cb3fa5f b8c071c
| | Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| | Date:   Wed Mar 20 19:51:06 2024 -0700
| |
| |     Merge branch <span class="hljs-string">'main'</span> into dev
| |
* | commit cb3fa5f3bdbdcff3d9a8c844cda99d46bf64e337
| | Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| | Date:   Sat Mar 9 22:00:49 2024 -0800
| |
| |     Add --staged flag to git restore subcommand
| |
| |     Signed-off-by: Jacob Stopak &lt;jacob@initialcommit.io&gt;
| |
| * commit b8c071cb9a1653748525aa01c2b6bafe06ed9100
|/  Author: Jacob Stopak &lt;jacob@initialcommit.io&gt;
|   Date:   Wed Mar 20 19:50:53 2024 -0700
|
|       Correct license specified <span class="hljs-keyword">in</span> pyproject.toml from MIT to GNU GPLv2
|
|       Signed-off-by: Jacob Stopak &lt;jacob@initialcommit.io&gt;
|
* commit 32a3a3fca583f6c68225b974716e74b557a1a094
| Author: Jacob Stopak &lt;49353917+initialcommit-io@users.noreply.github.com&gt;
| Date:   Tue Aug 22 11:31:38 2023 -0700
|
|     Update README.md
</code></pre>
<p>Unfortunately, this is not so pretty at all. This long, garbled list of commit IDs, names, dates, and commit messages is definitely not something most folks would consider user-friendly.</p>
<p>The <code>--graph</code> option supplied above does show the commit relationships by drawing little lines connecting each commit in the terminal, but the purely text-based nature of this is just not intuitive to most people at a glance.</p>
<p>Now consider the following gamified representation of Git’s commit history:</p>
<p><a target="_blank" href="https://devlands.com"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740594184258/8d5a33c8-ad60-4496-a50d-a27fc6b8e752.png" alt="Image captured from Devlands, the gamified Git interface and tutorial, showing the project's commit history and branches" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<p>Now we’re talkin’! In this image, each Git commit is represented by a white block with a shortened 6-character commit ID.</p>
<p>Each white commit block points back to its parent commit with an arrow, forming very clear chains of commits that make up Git branches.</p>
<p>You might have noticed that some of the white commit blocks have colored blocks sitting on top of them. The green blocks are <a target="_blank" href="https://initialcommit.com/blog/git-branches">branch names</a>, the yellow blocks are <a target="_blank" href="https://initialcommit.com/blog/git-tag">Git tags</a>, the blue block is <a target="_blank" href="https://initialcommit.com/blog/what-is-git-head">Git’s HEAD pointer</a>, and the red blocks are remote-tracking branches. These are collectively referred to as <a target="_blank" href="https://initialcommit.com/blog/what-is-git-head#git-refs-and-heads">Git refs</a>.</p>
<p>Besides being able to easily distinguish between them, representing ref types as different colored blocks clarifies another often-confusing Git concept. In Git, branches (along with other refs types) are just “pointers” to a specific commit. It is tempting to think of a branch as a series of connected commits that share a history – and conceptually this is correct – but in Git, a branch is really just a glorified label pointing to a specific commit.</p>
<p>In this gamified world, you can <em>literally walk through your commit history</em> to see, interact with, and examine the code changes in any commit.</p>
<h2 id="heading-summary">Summary</h2>
<p>In this article, we explored how Git’s fundamental concepts - the working directory, staging area, and commit history - can be difficult to grasp due to their abstract nature.</p>
<p>To make these concepts more accessible, we introduced a gamified, visual approach that transforms them into something tangible: an immersive game world where files and commits are represented as interactive blocks.</p>
<p>By presenting Git this way, beginner coders, students, and developers of all experience levels can intuitively learn Git concepts and commands, and confidently apply them in professional projects.</p>
<h2 id="heading-try-it-yourself">Try it Yourself</h2>
<p>The images in this post were captured in <a target="_blank" href="https://devlands.com">Devlands</a>, the first and only <em>gamified Git interface and tutorial</em>, which I’m building in Python.</p>
<p>In Devlands, not only can you walk through your codebase… You can also learn Git concepts and commands with a character-guided tutorial, simulate and run Git commands directly in the game, see their results applied in the game world in real time, and use AI to explain code you don’t understand.</p>
<p>If you or someone you know is a visual learner, beginner coder, or newer Git user, <a target="_blank" href="https://devlands.com">consider checking it out!</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Trie Data Structures Work – Validate User Input with Automated Trie Visualization ]]>
                </title>
                <description>
                    <![CDATA[ Data structures play a vital role in computer science. They are essential for designing efficient software infrastructure.  Simply put, a data structure is a way of organizing and storing data in a computer so that it can be accessed and manipulated ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-validate-user-input-with-automated-trie-visualization/</link>
                <guid isPermaLink="false">66baef4c90ea1057a46fdf9a</guid>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ visualization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel García Solla ]]>
                </dc:creator>
                <pubDate>Wed, 05 Apr 2023 21:24:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/Screenshot-2023-04-04-110030.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Data structures play a vital role in computer science. They are essential for designing efficient software infrastructure. </p>
<p>Simply put, a data structure is a way of organizing and storing data in a computer so that it can be accessed and manipulated reliably. Also, it provides a set of operations such as inserting, deleting, or searching, with their respective computational costs.</p>
<h2 id="heading-why-are-data-structures-useful">Why Are Data Structures Useful?</h2>
<p>The value of data structures lies in their ability to approach complex problems in a simpler and more comprehensive way. As they allow for the storage and retrieval of large amounts of data, they become especially important in today's world. Data is being generated at an unprecedented rate. And that data is later processed to extract valuable insights with the goal of developing new products and services that make our lives easier. </p>
<p>Another one of the main advantages of data structures is their ability to reduce the time complexity of certain algorithms. By using the appropriate data structure, you can perform operations such as searching, sorting, and inserting data in sub-linear time. </p>
<p>For example, using a <strong>Hash Table</strong> instead of a <strong>Linked List</strong> to store data enables us to access any element of the structure in constant time, reducing the complexity from <strong>O(n)</strong> to <strong>O(1)</strong>.</p>
<p>In this context, one of the most important aspects of data structures is their ability to organize data in a way that allows for efficient memory usage and reduces the time required to perform specific tasks. </p>
<p>Choosing the right data structure for a large-scale problem is a critical decision that can greatly impact the performance of an algorithm or software application. They also serve as the foundation for many core computer science concepts, such as algorithms, databases, and compilers. </p>
<p>So, in order to fully grasp their significance, you need to understand their inner workings and analyze their strengths and weaknesses.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/1920px-Vector_Rope_example.svg-1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>An example of a Rope data structure. Mainly udes to manage large raw strings. Image gotten from [Wikipedia](https://en.wikipedia.org/wiki/Rope</em>%28data<em>structure%29)</em></p>
<h2 id="heading-different-types-of-data-structures">Different Types of Data Structures</h2>
<p>There are numerous types of data structures, including the previously mentioned linked lists, arrays, stacks, queues, trees, and graphs. And each has its own set of use cases and benefits. </p>
<h3 id="heading-what-is-a-trie-data-structure">What is a Trie Data Structure?</h3>
<p>One particularly interesting data structure we will focus on in this article is the Trie, a tree-like data structure employed to store a dynamic set or associative array where the keys are typically strings. </p>
<p>Commonly, we use tries in tasks such as searching and auto-completion, where a large dataset of strings needs to be efficiently stored, checked, or searched.</p>
<p>The <strong>Trie</strong> is particularly efficient for tasks that involve searching through a large set of strings, as it can perform these tasks with a time complexity of <strong>O(m)</strong>, where m is the length of the searched string. This makes the Trie an attractive choice for applications such as dictionaries, autocomplete features, and IP routing tables. </p>
<p>Despite the numerous advantages offered by Tries, one of the main challenges associated with their implementation is their potential complexity, particularly in their instantiation and visualization. </p>
<p>The visualization of data structures is an essential aspect of understanding their basis and evaluating their performance. But visualizing Tries can become increasingly difficult as the number of nodes and branches grows. </p>
<p>This can lead to confusion and misunderstandings, making it harder for developers and researchers to comprehensively understand the Trie's behavior and throughput. For this reason, this article shows you how to automate the visualization of Trie data structures. </p>
<h3 id="heading-benefits-of-automating-the-visualization-process">Benefits of Automating the Visualization Process</h3>
<p>By automating the visualization process, we unlock a multitude of advantages that can positively impact the overall software development process, transcending the boundaries of traditional visualization techniques. </p>
<p>First and foremost, automation brings with it the gift of efficiency. By eliminating the need for manual visualization and enabling the instantaneous generation of visual representations, we drastically reduce the time spent on creating and understanding Trie diagrams. </p>
<p>This newfound efficiency frees up valuable time for other tasks, allowing us to focus on optimizing and tackling major abstract challenges, ultimately driving progress in the field.</p>
<p>In addition, automation paves the way for consistency and accuracy in visualizing Tries. The human element is prone to errors, leading to misunderstandings and misinterpretations of the underlying data structure. Automating the visualization process removes these potential pitfalls, ensuring that the visual representations generated are trustworthy, precise, and true to the data structure. </p>
<p>Also, automation empowers <strong>scalability</strong>, enabling the visualization of even the most complex and large-scale datasets. As the size of a Trie increases, so does the difficulty of manual visualization. Automation sidesteps this issue by generating visual representations regardless of the complexity or size of the Trie. This grants researchers and developers an unprecedented level of insight into their systems.</p>
<p>Lastly, automation fosters accessibility and inclusivity in the world of data structure visualization. </p>
<p>Traditionally, creating and interpreting visualizations required a certain level of expertise and experience. But by automating this process, we democratize access to the benefits of visualization. This makes it possible for individuals with varying levels of expertise to analyze and understand Trie data structures. </p>
<p>This, in turn, can inspire collaboration and innovation across a wide range of disciplines and industries.</p>
<h3 id="heading-heres-what-well-cover-in-this-guide"><strong>Here's what we'll cover in this guide:</strong></h3>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-a-trie">What is a Trie</a>?</li>
<li><a class="post-section-overview" href="#heading-main-components-of-a-trie-data-structure">Main Components of a Trie Data Structure</a></li>
<li><a class="post-section-overview" href="#heading-operations-you-can-perform-on-a-trie">Operations You Can Perform on a Trie</a></li>
<li><a class="post-section-overview" href="#heading-how-to-implement-a-trie">How to Implement a Trie</a></li>
<li><a class="post-section-overview" href="#heading-how-to-visualize-a-trie">How to Visualize a Trie</a></li>
</ol>
<h2 id="heading-what-is-a-trie">What is a Trie?</h2>
<p>A Trie is a unique and powerful data structure in computer science. It's used to store and manipulate associative arrays or dynamic sets where the keys are typically strings. It is also known as a prefix, radix, or digital tree. </p>
<p>Originating from the term "retrieval," the Trie is a tree-like structure that efficiently organizes and searches through large sets of strings based on their prefixes. This makes it an ideal choice for applications such as dictionaries or spell-checking features.</p>
<p>The Trie comprises nodes connected by branches, each one representing a single character in a string. The root node is usually empty or holds a special value, while the leaf nodes signify the end of a string. </p>
<p>As we traverse from the root node to a leaf node, we construct the string by concatenating the characters represented by each node. </p>
<h3 id="heading-advantages-of-the-trie-data-structure">Advantages of the Trie Data Structure</h3>
<p>Unlike other tree data structures like binary search trees, Tries don't store the actual keys associated with the nodes. Instead, the position of a node within the Trie structure defines the key.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of a Trie containing 4 english words</em></p>
<p>One of the main advantages of Tries compared to other alternatives like <strong>BSTs (Binary Search Trees)</strong> is their ability to perform search, insert, and delete operations with a time complexity of <strong>O(m)</strong>. In this case, m is the length of the key (word) being searched, inserted, or deleted. </p>
<p>This is particularly efficient when working with large datasets, as the complexity is independent of the number of keys stored in the Trie. In other words, the performance of these operations does not degrade as the Trie grows in size.</p>
<p>Tries have several other notable features, including:</p>
<ol>
<li>Prefix sharing: A Trie stores strings by sharing their common prefixes, reducing memory usage and providing a compact dataset representation. This feature is particularly beneficial when working with large sets of strings that share many common prefixes.</li>
<li>Alphabet-independent size: The size of a Trie is not dependent on the size of the alphabet of the words it contains, making it well-suited for a wide range of applications and datasets.</li>
<li>Support for advanced search operations: Tries can perform advanced search operations, such as prefix matching, autocomplete suggestions, and approximate string matching, which are difficult or inefficient to implement using other data structures.</li>
<li>Space optimization with compressed Tries: Variations of the Trie data structure, such as Radix Tries, can further optimize memory usage by collapsing multiple nodes with single child nodes into a single node, resulting in a more compact structure.</li>
</ol>
<p>Still, Tries are not without their drawbacks. One primary concern is their potential space inefficiency. Tries can consume a considerable amount of memory, particularly when working with large alphabets or datasets with few shared prefixes. This issue can be mitigated to some extent through compression techniques and alternative Trie implementations. </p>
<p>In summary, when deciding whether or not to use a Trie, you should consider the specific requirements of your application carefully, the nature of your dataset, and the trade-offs between performance, memory usage, and complexity.</p>
<h2 id="heading-main-components-of-a-trie-data-structure">Main Components of a Trie Data Structure</h2>
<p>A Trie consists of several fundamental components that work together to compose its basis. Understanding these elements is crucial for solidly comprehending Tries and their full potential. </p>
<p>Here, we will discuss the main parts of a trie, some of them previously mentioned:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sample Trie to locate and visualize the corresponding elements</em></p>
<ol>
<li><strong>Nodes</strong>: A Trie consists of nodes, each representing a single character in a string. Every Trie has a root node, above colored in red, which is typically empty or holds a special value. The other nodes in the Trie correspond to individual characters of the stored strings.</li>
<li><strong>Edges</strong>: Edges, or branches, connect the nodes in a Trie. Each edge links a parent node to a child node and represents a transition between two characters in a string. The edges help form the paths from the root node to the leaf nodes, which correspond to complete strings.</li>
<li><strong>Leaf Nodes</strong>: Leaf nodes <em>(colored in green)</em> are the terminal nodes, signifying the end of a string. Depending on the specific application, they may contain additional information, such as the string's frequency, value, or associated data.</li>
<li><strong>Pointers</strong>: Each node in a Trie typically contains an array or set of pointers, one for each possible character in the alphabet. These pointers reference the child nodes corresponding to a string's next character. If a pointer is null or is not contained in the set, it indicates that there is no child node for that character.</li>
<li><strong>Common Prefixes</strong>: One of Trie's defining characteristics is its ability to share common prefixes among stored strings. This feature <em>(optional depending on the applied problem)</em> provides support when performing prefix-based operations and searches.</li>
<li><strong>End-of-Word Flag</strong>: A marker or <strong>end</strong> flag is often used to differentiate between complete strings and prefixes. This boolean value is set in a node to indicate that the path from the root node to that node represents a complete string in the Trie.</li>
</ol>
<h2 id="heading-operations-you-can-perform-on-a-trie">Operations You Can Perform on a Trie</h2>
<p>Now that you've seen the fundamental elements of a Trie, you have a broad idea about their underlying operations. You also understand the trie's value as a data structure. </p>
<p>At this point, you should try to understand technically the complexity of each operation that can be performed on them.</p>
<h3 id="heading-how-to-insert-a-string-into-a-trie">How to Insert a String into a Trie</h3>
<p>Imagine the Trie as a tree with many branches, starting from a root node. To insert a string, begin at the root and follow these steps:</p>
<ul>
<li>For each character in the string, check if there's an edge (branch) corresponding to the character.</li>
<li>If there is, move to the child node connected by the edge.</li>
<li>If not, create a new node for the character, connect it to the current node with an edge, and move to the new node.</li>
<li>Once you reach the end of the string, mark the final node as the end of a word.</li>
</ul>
<p>Example: Insert "apple" and "ape" into an empty Trie</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-search-for-a-string-in-a-trie">How to Search for a String in a Trie</h3>
<p>To search for a string in a Trie, start at the root and follow these steps:</p>
<ul>
<li>For each character in the string, check if there's an edge corresponding to the character.</li>
<li>If there is, move to the child node connected by the edge.</li>
<li>If there isn't, the string is not in the Trie, and the search fails.</li>
<li>If you reach the end of the string, check if the final node is marked as the end of a word. If it is, the search is successful.</li>
</ul>
<p>Example: Search for "ape" in the Trie containing "apple" and "ape"</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>Path followed by the search algorithm to check for the word <strong>"ape"</strong></em></p>
<h3 id="heading-how-to-delete-a-string-from-a-trie">How to Delete a String from a Trie</h3>
<p> To delete a string from a Trie, start at the root and follow this process:</p>
<ul>
<li>Search for the string, keeping track of the nodes and edges traversed.</li>
<li>If the string is not found, the deletion fails.</li>
<li>Remove the <strong>end</strong> flag from the final node if the string is found.</li>
<li>Starting from the final node, move back toward the root, deleting nodes and edges that don't have other children or don't belong to other complete words.</li>
</ul>
<p>Example: Delete "ape" from the Trie containing "apple" and "ape"</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-8.png" alt="Image" width="600" height="400" loading="lazy">
<em>Trie after the removal of the word <strong>"ape"</strong></em></p>
<p>By thinking about these operations as traversals through the Trie's branches, we can then more easily account for the memory and time complexity of each one. They are equivalent to tree <em>(or linked list)</em> traversal tasks.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/Artboard-1-copy-42@8x.png" alt="Image" width="600" height="400" loading="lazy">
<em>Table of average time and space complexities of Trie operations</em></p>
<p>As seen in the table, all the operations have the same linear time complexity <em>(being</em> <strong><em>n</em></strong> <em>the length of the word being processed)</em>. This means that they only require performing a single traversal across the word's characters to achieve the desired result. </p>
<p>But in terms of space, deletion and search don't need additional memory. This means that they have a constant complexity.</p>
<p>Finally, it is worth pointing out that the worst-case time complexity of the deletion operation could be in the order of <strong>O(2n)</strong>, having to traverse through the branch where the word to be deleted resides once more in order to remove possible unused nodes in the Trie.</p>
<h2 id="heading-how-to-implement-a-trie">How to Implement a Trie</h2>
<p>Now we will use Python to implement a Trie specifically designed for a validation problem (but you can tailor it for any given application).</p>
<p>The sample problem our implementation will solve is the following: given a board with <strong>NxN</strong> squares, we want a user to be able to introduce the coordinates of a specific square using a text message in order to select and operate with it. </p>
<p>For this purpose, the input will consist of a series of alphabetical characters to refer to the board's vertical axis, followed by another set of numerical characters to select the remaining axis.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-16.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sample 6x6 board</em></p>
<p>In this case, we can use regular expressions or similar techniques to validate if the user's input matches the required structure and format. But if we don't mind our program consuming more memory, we have the alternative of using a Trie. </p>
<p>This choice may, at first glance, seem overly inefficient in terms of memory since we must create and use a specific data structure that consumes space during the entire execution of the program. </p>
<p>But using a Trie provides a constant validation time for all possible inputs, and since in this example the coordinates are short length strings, storing them in memory proves to be reasonable.</p>
<p>Note that in this example, the Trie search operation <em>(validation)</em> runs in "constant" time due to the fixed length of all its words. That is, as the board won't scale up during the program execution, the time complexity for searching a string remains constant.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> random
<span class="hljs-keyword">import</span> math
<span class="hljs-keyword">import</span> urllib, json
<span class="hljs-keyword">from</span> pyvis.network <span class="hljs-keyword">import</span> Network
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TrieNode</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, inputChar</span>):</span>
        self.char = inputChar
        self.end = <span class="hljs-literal">False</span>
        self.children = {}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Trie</span>():</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, startingElements=None</span>):</span>
        self.root = TrieNode(<span class="hljs-string">""</span>)
        <span class="hljs-keyword">if</span> startingElements!=<span class="hljs-literal">None</span>:
          <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> startingElements: self.insert(i)
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">insert</span>(<span class="hljs-params">self, word</span>):</span>
        node = self.root
        <span class="hljs-keyword">for</span> char <span class="hljs-keyword">in</span> word:
            <span class="hljs-keyword">if</span> char <span class="hljs-keyword">in</span> node.children:
                node = node.children[char]
            <span class="hljs-keyword">else</span>:
                new_node = TrieNode(char)
                node.children[char] = new_node
                node = new_node
        node.end = <span class="hljs-literal">True</span>      
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">searchAndSplit</span>(<span class="hljs-params">self, x</span>):</span>
        node = self.root
        output = [<span class="hljs-string">""</span>, <span class="hljs-string">""</span>]
        <span class="hljs-keyword">for</span> char <span class="hljs-keyword">in</span> x:
            <span class="hljs-keyword">if</span> char <span class="hljs-keyword">in</span> node.children:
                node = node.children[char]            
            <span class="hljs-keyword">else</span>:
                <span class="hljs-keyword">return</span> []        
            output[<span class="hljs-number">1</span> <span class="hljs-keyword">if</span> node.end <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>] += node.char
        <span class="hljs-keyword">return</span> output <span class="hljs-keyword">if</span> node.end <span class="hljs-keyword">else</span> []

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">remove</span>(<span class="hljs-params">self, root, word, index = <span class="hljs-number">0</span></span>):</span>
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> root:
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

        <span class="hljs-keyword">if</span> index==len(word):
            <span class="hljs-keyword">if</span> root.end:
                root.end = <span class="hljs-literal">False</span>
            <span class="hljs-keyword">if</span> root.children=={}:
                <span class="hljs-keyword">del</span> root
                root = <span class="hljs-literal">None</span>
            <span class="hljs-keyword">return</span> root

        root.children[word[index]] = self.remove(root.children[word[index]], word, index + <span class="hljs-number">1</span>)

        <span class="hljs-keyword">if</span> (root.children=={}) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> root.end:
            <span class="hljs-keyword">del</span> root
            root = <span class="hljs-literal">None</span>
        <span class="hljs-keyword">return</span> root
</code></pre>
<p>Above, you can see the whole implementation. In short, it consists of two classes, <strong>TrieNode</strong> and <strong>Trie</strong>, which define the Trie's nodes and Trie structure itself, respectively. </p>
<p>The Trie class provides methods for inserting, searching, splitting <em>(which is a custom feature we will discuss in the visualization section)</em>, and removing words from the Trie. The TrieNode class represents individual nodes and their associated attributes. In this case, they are a string containing the corresponding node character and a hash table of characters associated with the pointers to the Trie's subbranches.</p>
<h2 id="heading-how-to-visualize-a-trie">How to Visualize a Trie</h2>
<p>Finally, after functionally implementing the Trie, we will use the Python library <strong><a target="_blank" href="https://pyvis.readthedocs.io/en/latest/">pyvis</a></strong> to define a function inside the Trie class that automatically produces a graph visualization of the data structure. This will result in an HTML file in which we can interact with the elements it contains.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">toGraph</span>(<span class="hljs-params">self</span>):</span>      
      g = Network(directed =<span class="hljs-literal">True</span>)      
      g.show_buttons()

      nodeIndex = <span class="hljs-number">1</span>
      currentNode = <span class="hljs-number">0</span>
      q = [self.root]      
      g.add_node(currentNode, label=<span class="hljs-string">""</span>, color=<span class="hljs-string">"red"</span>)
      tempLabels = {<span class="hljs-number">0</span>:<span class="hljs-string">""</span>}
      <span class="hljs-keyword">while</span> q!=[]:
        n = q.pop(<span class="hljs-number">0</span>)                     
        <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> n.children.values():
          <span class="hljs-keyword">if</span> i:
            tempLabels[nodeIndex] = tempLabels[currentNode]+i.char
            g.add_node(nodeIndex, label=tempLabels[currentNode]+i.char, color=<span class="hljs-string">"#48e073"</span> <span class="hljs-keyword">if</span> i.end <span class="hljs-keyword">else</span> <span class="hljs-string">"blue"</span>)
            g.add_edge(currentNode, nodeIndex)
            nodeIndex+=<span class="hljs-number">1</span>
            q.append(i)
        currentNode+=<span class="hljs-number">1</span>
      g.show(<span class="hljs-string">'nx.html'</span>)
</code></pre>
<p>As you can observe in the <strong>toGraph()</strong> function, we perform a <a target="_blank" href="https://youtu.be/xlVX7dXLS64"><strong>Breadth-First Search</strong></a> all over the Trie while creating the necessary nodes and edges <em>(connections between them)</em> inside a <strong>pyvis.network.Network</strong> object. </p>
<p>Also, it gives the end nodes a different color from the rest. This will help us understand the benefits that this visualization provides so we can simplify the execution of functions related to the processing and validation of strings in the previous example.</p>
<p>So to instantiate a Trie with the string coordinates of the example 6x6 board, we will pass a generator Python object to the Trie's constructor to insert each string into the data structure and plot it into a graph:</p>
<pre><code class="lang-python">tr = Trie((<span class="hljs-string">''</span>.join(chr(<span class="hljs-number">97</span>+int(j)) <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> str(i))+str(k) <span class="hljs-keyword">for</span> k <span class="hljs-keyword">in</span> range(<span class="hljs-number">6</span>) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">6</span>)))
tr.toGraph()
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>According to the coloring rules of the <strong>toGraph()</strong> function, all nodes containing only an alphabetic character are colored in blue, while all other nodes except the root one are colored in green. </p>
<p>If we increase the board size, we will notice that all the end nodes will have a different color than the nodes with alphabetic characters, as shown in the following graph section of a 16x16 board:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-30.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Thus, when performing a search or a BFS traversal, we can take advantage of the <strong>end</strong> flag to split the coordinates between alphabetic and numeric characters. This avoids an extra post-processing step after validating the user input. </p>
<p>Lastly, we can create a bigger Trie to see how it behaves on a larger scale.</p>
<pre><code class="lang-python">data = json.loads(urllib.request.urlopen(<span class="hljs-string">"https://raw.githubusercontent.com/dwyl/english-words/master/words_dictionary.json"</span>).read())
data = list(data.keys())
tr = Trie(random.sample(data, <span class="hljs-number">100</span>))
tr.toGraph()
</code></pre>
<p>By using this code, we are accessing an open-source English words dataset, selecting 100 random words, and inserting them into a new Trie. It gives as visualization output the following graph:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-31.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If you would like to work and customize Tries for specific projects interactively, you can access the complete code in the Colab Notebook provided below:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/cardstdani/practica-par/blob/main/TrieValidationExample.ipynb">https://github.com/cardstdani/practica-par/blob/main/TrieValidationExample.ipynb</a></div>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We have seen how visualizing a data structure or a problem input data can significantly enhance our understanding of its relationships and intricacies. It also offers us the chance to introduce new features that otherwise could not have been developed so easily without a proper and automated visioning. </p>
<p>In addition to Tries, the benefits of visualization can be extended to other data structures and algorithms. And it can foster a deeper understanding of the underlying logic and functionality. </p>
<p>Incorporating visualization techniques into the development process can significantly improve the efficiency and creativity of our work in computer science and data analysis. </p>
<p>In conclusion, by embracing visualization as a key component of our development process, we can unlock new opportunities for optimizing, troubleshooting and exploring the full potential of data structures and algorithms in various applications.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ An easy way to make word clouds for data scientists ]]>
                </title>
                <description>
                    <![CDATA[ By Kavita Ganesan About a year ago, I looked high and low for a Python word cloud library that I could use from within my Jupyter notebook. I needed it to be flexible enough to use counts or tfidf when needed or just accept a set of words and corresp... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/word-cloud-for-data-scientists-76b8a907e04e/</link>
                <guid isPermaLink="false">66c3678663ac6ce6ab8eba3c</guid>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ text mining ]]>
                    </category>
                
                    <category>
                        <![CDATA[ visualization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 23 Oct 2018 05:24:33 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*HYtC28uzCWtTK2r_cR_3CA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Kavita Ganesan</p>
<p>About a year ago, I looked high and low for a Python word cloud library that I could use from within my Jupyter notebook. I needed it to be flexible enough to use <code>counts</code> or <code>tfidf</code> when needed or just accept a set of words and corresponding weights.</p>
<p>I was a bit surprised that something like that did not already exist within libraries like <code>plotly</code>. All I wanted to do was to get a quick understanding of my text data and word vectors. I thought that was probably not too much to ask…</p>
<p>Here I am a year later, using my own <a target="_blank" href="https://github.com/kavgan/word_cloud">word_cloud</a> visualization library. Its not the prettiest or the most sophisticated, but it works for most cases. I decided to share it, so that others could use it as well. After <a target="_blank" href="https://github.com/kavgan/word_cloud">installation</a>, here are a few ways you can use it.</p>
<h4 id="heading-generate-word-clouds-with-a-single-text-document">Generate word clouds with a single text document</h4>
<p>This example show examples of how you can generate word clouds with just one document. While the colors can be randomized, in this example, the colors are based on the default color settings.</p>
<p>By default, the words are weighted by word counts unless you explicitly ask for tfidf weighting. Tfidf weighting makes sense only if you have a lot of documents to start with.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*HYtC28uzCWtTK2r_cR_3CA.png" alt="Image" width="800" height="743" loading="lazy">
<em>word cloud based on a single document</em></p>
<h4 id="heading-generate-word-clouds-from-multiple-documents">Generate word clouds from multiple documents</h4>
<p>Let’s say you have 100 documents from one news category, and you just want to see what the common mentions are.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*lKQBi3n4OfjawldVtXrU5g.png" alt="Image" width="800" height="844" loading="lazy">
<em>word cloud based on multiple documents</em></p>
<h4 id="heading-generate-word-clouds-from-existing-weights">Generate word clouds from existing weights</h4>
<p>Let’s say you have a set of words with corresponding weights, and you just want to visualize it. All you need to do is make sure that the weights are normalized between [0 - 1].</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/1*NyGmBmZ4OOiOPLir9h4doA.png" alt="Image" width="800" height="579" loading="lazy">
<em>word cloud from existing weights</em></p>
<p>Hope you find this useful! Please feel free to propose changes to prettify the output - just open a pull request with your changes.</p>
<h3 id="heading-links">Links</h3>
<ul>
<li><a target="_blank" href="https://colab.research.google.com/drive/1AkdUKEFmaYom77r6KPh18jdQrplIQbKQ">See my Jupyter notebook with code examples</a></li>
<li><a target="_blank" href="https://github.com/kavgan/word_cloud">Start using word_cloud library</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Let me guide you through your first date with Docker ]]>
                </title>
                <description>
                    <![CDATA[ By Chandrabhan Singh Install Docker, create your first container, and more You may have seen Docker somewhere on the internet and you may feel curious about it. Now you want to take it to the next level. How about going on a date with Docker? No — I ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/let-me-guide-you-through-your-first-date-with-docker-f03f35567d95/</link>
                <guid isPermaLink="false">66d45dd7c7632f8bfbf1e3e9</guid>
                
                    <category>
                        <![CDATA[ containers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ docker image ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ visualization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 31 May 2018 19:38:50 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*aKHmBi9PuIUTpp0buimRsA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Chandrabhan Singh</p>
<h4 id="heading-install-docker-create-your-first-container-and-more">Install Docker, create your first container, and more</h4>
<p>You may have seen Docker somewhere on the internet and you may feel curious about it. Now you want to take it to the next level. How about going on a date with Docker? No — I am not kidding!</p>
<p>But, how do you plan a perfect first date? What should you do? Where to find the right resources? What prerequisites might you need?</p>
<p>The questions are endless. Follow these first-date guidelines, and you’ll be well on your way to landing a second.</p>
<h3 id="heading-planning-your-date">Planning your date</h3>
<p>Getting to know your date before you start planning is crucial to crafting a memorable first experience. It will likely boost your confidence during the meeting, as well.</p>
<p>It’s never too late to say Hi. <a target="_blank" href="https://medium.com/@chandrabhan_/docker-what-i-learned-bc3587e17f17">Here</a> is a short introduction to my first time meeting Docker if you’re interested.</p>
<p>Okay! So the road map we will follow today looks something like this:</p>
<ol>
<li>Setting up the Venue</li>
<li>The Pickup</li>
<li>The Conversation</li>
</ol>
<h3 id="heading-prelude"><strong>Prelude</strong></h3>
<p>The place where we will set up our date is the Docker engine.</p>
<p>Docker engine is no different from any other engine. It is a combination of various components working together.</p>
<p>We will see a few of these components later in this article. But for now, let’s decorate our machine with Docker. The installation process depends upon your operating system.</p>
<p>The key for uninterrupted execution is always to refer to an official website. Docker has this fantastic <a target="_blank" href="https://docs.docker.com/install/">guide</a>, where you can find out more about installation.</p>
<p>Docker comes in two flavors: Docker Community Edition (CE) and Docker Enterprise Edition (E.E.). For our demonstration purposes, we must stick to the community edition. The Enterprise Edition is paid. And besides, making an expensive reservation for your first date is not the best idea ?</p>
<h3 id="heading-the-venue">The Venue</h3>
<p>The core mantra for any propitious date is to choose the right meeting place. Meeting Docker is no different. First, we should decide on the platform. Cloud? Mac? Linux? Or Windows? Once we know our environment, we can choose the simplest way to set up the meeting place.</p>
<h4 id="heading-windows">Windows</h4>
<p>If your choice is Windows, the process for setup is quite simple. Remember our favorite process: Next, Next, Next, and Finish.</p>
<p>Jump to the download <a target="_blank" href="https://store.docker.com/editions/community/docker-ce-desktop-windows">page</a> and choose the “Edge channel.” Edge has experimental features and fits best for our learning purposes.</p>
<p><strong>Note!</strong> Docker for Windows needs the “Hyper-V” feature, but there is nothing to worry about — Docker will turn it on for you. However, it means that you can’t use Virtual Box.</p>
<h4 id="heading-linux">Linux</h4>
<p>When I first started experimenting on a Linux box, I thought it was going to be a nightmare. But to my relief, setting up Docker on a Linux distribution turned out to be simple. Again, there are many ways to install Docker on a Linux distribution.</p>
<p>My favorite is: “Install using the convenience script.” We grab a long shell script from the internet and then pipe it to a shell terminal.</p>
<p>How? Like this:</p>
<pre><code>sudo wget -qO- https:<span class="hljs-comment">//get.docker.com |sh</span>
</code></pre><p><strong>Done</strong>! Yeah, you have Docker on your machine up and running.</p>
<p>Now that the venue is all set, we are ready to proceed. But first, let’s make some inquiries to make sure everything is working fine here. The same as you might inquire with a restaurant before booking a table ?.</p>
<p>Let’s execute the below command in the terminal:</p>
<pre><code>docker version
</code></pre><p>You should see the installation details. It gives you information about the <strong>Client</strong> and <strong>Server</strong> version, the <strong>Go-lang</strong> version, and so on and so forth.</p>
<p>If the output of your command is somehow like the one below, the sun is shining, and the world is beautiful. <strong>Next</strong>: time to get ready for the “Pickup.”</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/n435DcbT4csc32tM5JOtrQrRDrvGHZZqhUx2" alt="Image" width="738" height="493" loading="lazy">
<em>Command output</em></p>
<h3 id="heading-the-pickup"><strong>The Pickup</strong></h3>
<p>As you may already be aware, Docker uses <strong>Images</strong> to create containers. These images are large binary immutable files.</p>
<p>An image contains application binaries and their dependencies. It may also contain other components such as a web server or even an OS.</p>
<p>We will need such images to create a container and run an application inside it.</p>
<p>So, where do these images live? Simple question, simple answer: on a Host. This host can be your machine or a registry somewhere on the internet. <a target="_blank" href="http://docker.io/">Docker</a> has its registry called Docker-Hub.</p>
<h4 id="heading-to-avoid-wandering-you-should-know-the-right-pickup-location-for-your-date">To avoid wandering, you should know the right pickup location for your date.</h4>
<p>To make your first date smoother, I found the exact location of an image that I can share with you. Excited enough? Here you go!</p>
<pre><code>docker pull chandrabhan/dotnetconsole
</code></pre><p>Let’s confirm that we are at the right location. ?</p>
<pre><code>docker image ls
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/ESkhGnOlmgnvsNWlJwQi45OdWHMWXM0m2wPD" alt="Image" width="800" height="327" loading="lazy">
<em>command output</em></p>
<p>Here you can see various properties of the images on your machine. Cool, it looks like things are going good so far.</p>
<p>Before moving further, let’s break down the previous two commands and understand what’s going on here.</p>
<p>With <code>Docker pull</code>, we asked Docker Daemon to pull an image for us. The Daemon could not find the image in the local registry, so it went ahead and pulled a remote copy from Docker-Hub.</p>
<p>Through <code>docker image ls</code> we saw all available images and their properties.</p>
<p>I must admit, I am getting excited. We’ve done a great job so far. Next, let the interaction begin.</p>
<h3 id="heading-the-conversation">The Conversation</h3>
<h4 id="heading-start-the-conversation-and-things-will-turn-out-in-your-favor">Start the conversation, and things will turn out in your favor.</h4>
<p>So again, to make it smoother for you, I want to offer you a few icebreakers.</p>
<p>We will create some containers for .Net Core framework applications. The first one will be a simple console application. The other will be a bit more colorful — a web application.</p>
<pre><code>docker run chandrabhan/dotnetconsole
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/CX7U8rR4b1bPzulYe15hEShC5IFrYEAy1Y3k" alt="Image" width="800" height="322" loading="lazy">
<em>command output</em></p>
<p>Magnificent! Did you see what happened there? This stuff is amazing. A .Net core application is running inside a container. Docker went ahead and created a container and executed the application inside it. And as soon as the console application ends, the container exists!</p>
<p>Let’s see how many containers we have in our machine:</p>
<pre><code>docker container ls -a
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/tuXcPX2nL8L7UQ5huyqHwvKip6Lm8-qFu0Cv" alt="Image" width="800" height="307" loading="lazy">
<em>command output</em></p>
<p>What you see here is the list of containers on your machine. You can identify a container by its <code>**ID**</code>. The output tells us when the container was <code>**CREATED**</code> and what it’s current <code>**STATUS**</code> is. The container we created is in <code>**Exited**</code> status. Remember? Our application is exited! So is the container.</p>
<p>It looks like the conversation is progressing well, so let’s keep going.</p>
<pre><code>docker run -it --rm -p <span class="hljs-number">5000</span>:<span class="hljs-number">80</span> --name app chandrabhan/aspdotnet
</code></pre><p>Go to your favorite browser and browse <code>http://localhost:5000</code>. You should see more amazing stuff.</p>
<p>An ASP.Net core web app is running inside a container:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/bE3jqk9-iKAtDEdeHgqqiNYhCe2SXvAEOZ1c" alt="Image" width="800" height="395" loading="lazy">
<em>containerized - sample ASP.Net application</em></p>
<p>Before moving further, let’s see the anatomy of the above command.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/inCu2ZgNwFRlxd4z9BN4hM7344sBOG53BB4I" alt="Image" width="800" height="361" loading="lazy">
<em>command anatomy</em></p>
<p>Did you notice? This time we did not pull the image, but we were still able to create a container out of it. When you execute <code>docker run</code>, Docker daemon tries to find a local copy of the image. If it cannot, it goes ahead and tries to find it in the default registry (Docker-Hub in this case).</p>
<p>I believe our planning was excellent and so was the execution. Let’s rewind what we did and review how we planned an auspicious date with Docker ?.</p>
<h3 id="heading-rewinding"><strong>Rewinding</strong></h3>
<ol>
<li>First, we installed Docker. We saw how the installation process varies depending on the operating system.</li>
<li>Then we went ahead and pulled an image from the Docker-Hub registry, a simple .Net Core console app.</li>
<li>Once we had this image on our machine, we used Docker to create a container out of this image.</li>
<li>We also saw how to pull an image and run a container through a single command.</li>
</ol>
<p>Here is an illustration that may help you understand a high-level picture.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/PuQLeHlccMgOtNb5VFtvC0uuYnEjuaVb9J22" alt="Image" width="800" height="298" loading="lazy">
<em>illustration: Docker client and daemon</em></p>
<h3 id="heading-follow-up">Follow up</h3>
<h4 id="heading-out-of-sight-out-of-mind">Out of sight out of mind</h4>
<p>Following up is as important as any other stage during the date. Now I should leave you with your date, and would like to hear how it went. Below are a few links that may be useful:</p>
<ul>
<li><a target="_blank" href="https://github.com/SinghChandrabhan/DockerSamples">Github</a></li>
<li><a target="_blank" href="https://hub.docker.com/u/chandrabhan">Docker hub</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
