<?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[ algorithms - 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[ algorithms - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 17 May 2026 04:37:54 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/algorithms/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Spam Email Detector with Python and Naive Bayes Classifier ]]>
                </title>
                <description>
                    <![CDATA[ Ever wondered how Gmail knows that an email promising you $10 million is spam? Or how it catches those "You've won a free iPhone!" messages before they reach your inbox? In this tutorial, you'll build ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-spam-email-detector-with-python-and-naive-bayes-classifier/</link>
                <guid isPermaLink="false">69b0a8f8abc0d95001af6574</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Maku Gideon ]]>
                </dc:creator>
                <pubDate>Tue, 10 Mar 2026 23:27:52 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/92eb401b-fce3-411b-9b0b-02ba486586cb.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Ever wondered how Gmail knows that an email promising you $10 million is spam? Or how it catches those "You've won a free iPhone!" messages before they reach your inbox?</p>
<p>In this tutorial, you'll build your own spam email classifier from scratch using the Naive Bayes algorithm. By the end, you'll have a working model that achieves over 97% accuracy—and you'll understand exactly how it works under the hood.</p>
<p>This project was inspired by the <a href="https://www.amazon.com/dp/B08WK2HCWL">Python Machine Learning Workbook for Beginners</a> by AI Publishing, which offers excellent hands-on ML projects for those starting their journey. <em>(Note: I have no affiliation with the authors — I simply found it a useful resource.)</em></p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#why-naive-bayes-for-spam-detection">Why Naive Bayes for Spam Detection?</a></p>
</li>
<li><p><a href="#how-to-set-up-your-environment">How to Set Up Your Environment</a></p>
</li>
<li><p><a href="#how-to-load-and-explore-the-dataset">How to Load and Explore the Dataset</a></p>
</li>
<li><p><a href="#how-to-visualize-the-data-distribution">How to Visualize the Data Distribution</a></p>
</li>
<li><p><a href="#how-to-analyze-word-patterns-with-word-clouds">How to Analyze Word Patterns with Word Clouds</a></p>
</li>
<li><p><a href="#preprocessing-the-text-data">Preprocessing the Text Data</a></p>
</li>
<li><p><a href="#how-to-convert-text-to-numerical-features">How to Convert Text to Numerical Features</a></p>
</li>
<li><p><a href="#how-to-train-the-naive-bayes-classifier">How to Train the Naive Bayes Classifier</a></p>
</li>
<li><p><a href="#how-to-evaluate-model-performance">How to Evaluate Model Performance</a></p>
</li>
<li><p><a href="#testing-on-individual-emails">Testing on Individual Emails</a></p>
</li>
<li><p><a href="#key-takeaways">Key Takeaways</a></p>
</li>
</ul>
<h2 id="heading-what-youll-learn">What You'll Learn</h2>
<ul>
<li><p>How email spam filters actually work</p>
</li>
<li><p>The intuition behind the Naïve Bayes algorithm</p>
</li>
<li><p>Text preprocessing techniques for machine learning</p>
</li>
<li><p>How to evaluate classification models</p>
</li>
<li><p>Building a complete spam detection pipeline in Python</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>You should have basic familiarity with Python and some understanding of fundamental machine learning concepts. Don't worry if you're still learning—I'll explain everything as we go.</p>
<h2 id="heading-why-naive-bayes-for-spam-detection">Why Naive Bayes for Spam Detection?</h2>
<p>Before we dive into code, let's understand why Naive Bayes is particularly well-suited for this task.</p>
<p>Imagine you receive an email containing words like "free," "winner," "click here," and "limited time offer." Your brain immediately flags this as suspicious. The Naive Bayes algorithm does something similar—it calculates the probability that an email is spam based on the words it contains.</p>
<p>The algorithm is called "naive" because it makes a simplifying assumption: it treats each word as independent of every other word. In reality, word combinations matter (think "free trial" vs. "free money"), but this simplification works remarkably well in practice.</p>
<p><strong>Why Choose Naive Bayes?</strong></p>
<ul>
<li><p><strong>Speed</strong>: It trains incredibly fast, even on large datasets</p>
</li>
<li><p><strong>Efficiency</strong>: Requires minimal training data to produce reliable results</p>
</li>
<li><p><strong>Simplicity</strong>: Easy to implement and interpret</p>
</li>
<li><p><strong>Performance</strong>: Despite its simplicity, it often outperforms more complex algorithms for text classification</p>
</li>
</ul>
<p><strong>Limitations to keep in mind:</strong></p>
<ul>
<li><p>The independence assumption means it can't capture relationships between words</p>
</li>
<li><p>If a word appears in the test data but never appeared in training, the algorithm assigns it zero probability (though there are ways to handle this)</p>
</li>
</ul>
<p>Now let's build our spam detector.</p>
<h2 id="heading-how-to-set-up-your-environment">How to Set Up Your Environment</h2>
<p>First, install the required libraries. Open your terminal or run this in a Jupyter notebook cell:</p>
<pre><code class="language-python">
%pip install regex wordcloud numpy pandas seaborn matplotlib scikit-learn
</code></pre>
<p>Here's a quick summary of what each library does:</p>
<ul>
<li><p><code>regex</code> / <code>re</code> — for cleaning text using pattern matching</p>
</li>
<li><p><code>wordcloud</code> — for visualizing which words appear most frequently</p>
</li>
<li><p><code>numpy</code> and <code>pandas</code> — for data loading and manipulation</p>
</li>
<li><p><code>seaborn</code> and <code>matplotlib</code> — for charts and visualizations</p>
</li>
<li><p><code>scikit-learn</code> — provides the Naive Bayes classifier, vectorizer, and evaluation tools</p>
</li>
</ul>
<p>Once installation is complete, import everything at the top of your script or notebook. Grouping all imports at the top is a Python best practice — it makes dependencies easy to spot at a glance.</p>
<pre><code class="language-python"># Data manipulation and analysis
import pandas as pd
import numpy as np

# Data visualization
import seaborn as sns
import matplotlib.pyplot as plt

# Natural language processing
import nltk
import re
from nltk.corpus import stopwords

# Machine learning
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score

# Word cloud visualization
from wordcloud import WordCloud
</code></pre>
<h2 id="heading-how-to-load-and-explore-the-dataset">How to Load and Explore the Dataset</h2>
<p>We'll use a dataset of labeled emails. You can download it from <a href="https://bit.ly/3j9Uh7h">Kaggle</a> or use any similar email dataset with <code>text</code> and <code>spam</code> columns.</p>
<p>Use pandas' <code>read_csv()</code> function to load the dataset from a CSV file into a DataFrame — a table-like structure that makes it easy to inspect and manipulate data. The <code>head()</code> method then displays the first 5 rows so you can confirm the data loaded correctly and understand its structure.</p>
<pre><code class="language-python">message_dataset = pd.read_csv('emails.csv')
message_dataset.head()
</code></pre>
<p><strong>Output:</strong></p>
<table>
<thead>
<tr>
<th></th>
<th>text</th>
<th>spam</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>Subject: naturally irresistible your corporate...</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>Subject: the stock trading gunslinger fanny i...</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>Subject: unbelievable new homes made easy im ...</td>
<td>1</td>
</tr>
<tr>
<td>3</td>
<td>Subject: 4 color printing special request add...</td>
<td>1</td>
</tr>
<tr>
<td>4</td>
<td>Subject: do not have money , get software cds ...</td>
<td>1</td>
</tr>
</tbody></table>
<p>Next, call <code>shape</code> on the DataFrame to check its dimensions — this returns a tuple of (rows, columns) and is a quick way to confirm you loaded the full dataset without truncation.</p>
<pre><code class="language-python"># Get the dimensions of our dataset (rows, columns)
message_dataset.shape
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-plaintext">(5728, 2)
</code></pre>
<p>The dataset contains 5,728 emails with two columns: <code>text</code> (the email content) and <code>spam</code> (1 for spam, 0 for legitimate emails).</p>
<h2 id="heading-how-to-visualize-the-data-distribution">How to Visualize the Data Distribution</h2>
<p>Before training any model, it's crucial to understand your data. Let's see how spam and legitimate emails are distributed.</p>
<p><code>value_counts()</code> tallies how many emails belong to each class (spam vs. legitimate). Chaining <code>.plot(kind="pie")</code> on the result converts those counts directly into a pie chart. The <code>autopct="%1.0f%%"</code> argument tells matplotlib to label each slice with its percentage, rounded to the nearest whole number.</p>
<pre><code class="language-python">plt.rcParams["figure.figsize"] = [8, 10]
message_dataset.spam.value_counts().plot(kind="pie", autopct="%1.0f%%")
</code></pre>
<p><strong>Output:</strong></p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769379922505/de29f062-db6b-4f7c-87ad-bf03440cc3fc.png" alt="de29f062-db6b-4f7c-87ad-bf03440cc3fc" width="600" height="400" loading="lazy">

<p>You'll see that approximately 24% of emails in the dataset are spam, while 76% are legitimate. This is a moderately imbalanced dataset, which we'll keep in mind when evaluating our model.</p>
<h2 id="heading-how-to-analyze-word-patterns-with-word-clouds">How to Analyze Word Patterns with Word Clouds</h2>
<p>Word clouds provide an intuitive visualization of the most frequent words in a text corpus. Words that appear more often are rendered larger. Let's create separate word clouds for spam and legitimate emails to identify distinguishing patterns.</p>
<p>First, we need to remove stop words — common words like "the," "is," and "at" that appear everywhere and carry no meaningful signal for classification. NLTK's <code>stopwords.words("english")</code> returns a pre-built list of these words. The <code>apply()</code> method runs a function across every row in the column, and the lambda inside it splits each email into individual words, filters out any stop words, then rejoins the remaining words into a clean string.</p>
<pre><code class="language-python">stop = stopwords.words("english")

message_dataset["text_without_sw"] = message_dataset["text"].apply(
    lambda x: "".join([item for item in x.split() if item not in stop])
)
</code></pre>
<p>Now let's visualize the spam emails. We filter the DataFrame to rows where <code>spam == 1</code>, join all that text into a single large string, and pass it to <code>WordCloud().generate()</code>. The <code>imshow()</code> function renders the resulting image, and <code>axis("off")</code> hides the x/y axes since they're not meaningful for an image display.</p>
<pre><code class="language-python">message_dataset_spam = message_dataset[message_dataset["spam"] == 1]

plt.rcParams["figure.figsize"] = [8, 10]
text = ' '.join(message_dataset_spam['text_without_sw'])
wordcloud2 = WordCloud().generate(text)

plt.imshow(wordcloud2)
plt.axis("off")
plt.show()
</code></pre>
<p><strong>Output:</strong></p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769379941156/d33d8b61-7ec4-4044-a98a-c7b9ce95eabf.png" alt="d33d8b61-7ec4-4044-a98a-c7b9ce95eabf" width="600" height="400" loading="lazy">

<p>Now do the same for legitimate emails by filtering to rows where <code>spam == 0</code>:</p>
<pre><code class="language-python">message_dataset_ham = message_dataset[message_dataset["spam"] == 0]

plt.rcParams["figure.figsize"] = [8, 10]
text = ' '.join(message_dataset_ham['text_without_sw'])
wordcloud2 = WordCloud().generate(text)

plt.imshow(wordcloud2)
plt.axis("off")
plt.show()
</code></pre>
<p><strong>Output:</strong></p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769379947878/368e5251-3072-423f-b298-fb00d03254f3.png" alt="368e5251-3072-423f-b298-fb00d03254f3" width="600" height="400" loading="lazy">

<p><strong>Key observations:</strong></p>
<ul>
<li><p><strong>Spam emails</strong> frequently contain promotional language: "free," "money," "offer," "click," "please"</p>
</li>
<li><p><strong>Legitimate emails</strong> contain more conversational and work-related terms: "company," "time," "thanks"</p>
</li>
</ul>
<p>You'll also notice the word "enron" appearing prominently in the legitimate emails cloud. This is because the non-spam emails in this dataset are drawn from the publicly available <strong>Enron email corpus</strong> — a large collection of real internal emails from Enron Corporation that was released during their 2001 fraud investigation. It has since become one of the most widely used benchmark datasets in NLP research, which is why "enron" shows up so frequently as a word in legitimate email content.</p>
<p>These patterns give us confidence that word-based classification will work well.</p>
<h2 id="heading-how-to-preprocess-the-text-data">How to Preprocess the Text Data</h2>
<p>Raw text needs cleaning before machine learning algorithms can process it effectively. Let's first separate our features from our labels. In ML terminology, <code>X</code> holds the inputs (the email text we use to make predictions) and <code>y</code> holds the target labels (1 for spam, 0 for legitimate).</p>
<pre><code class="language-python">X = message_dataset["text"]
y = message_dataset["spam"]
</code></pre>
<p>Now we'll define a function to clean the text. The <code>re.sub()</code> function from Python's built-in <code>re</code> module performs pattern-based substitution using regular expressions. We call it three times in sequence:</p>
<ol>
<li><p><code>re.sub('[^a-zA-Z]', ' ', doc)</code> — replaces anything that isn't a letter (numbers, punctuation, symbols) with a space. This strips noise that doesn't help with classification.</p>
</li>
<li><p><code>re.sub(r'\s+[a-zA-Z]\s+', ' ', document)</code> — removes isolated single characters (like "I" or "a" left behind after removing punctuation) by matching any single letter surrounded by whitespace.</p>
</li>
<li><p><code>re.sub(r'\s+', ' ', document)</code> — collapses multiple consecutive spaces into a single space, tidying up any extra gaps created by the previous two steps.</p>
</li>
</ol>
<pre><code class="language-python">def clean_text(doc):
    document = re.sub('[^a-zA-Z]', ' ', doc)
    document = re.sub(r'\s+[a-zA-Z]\s+', ' ', document)
    document = re.sub(r'\s+', ' ', document)
    return document
</code></pre>
<p>Apply this cleaning function to every email in the dataset. We first convert the pandas Series to a plain Python list using <code>list()</code>, then loop through each email, clean it, and collect the results in <code>X_sentences</code>.</p>
<pre><code class="language-python"># Create an empty list to store cleaned emails
X_sentences = []

# Convert the pandas Series to a list for iteration
reviews = list(X)

# Clean each email and add it to our list
for rev in reviews:
    X_sentences.append(clean_text(rev))
</code></pre>
<h2 id="heading-how-to-convert-text-to-numerical-features">How to Convert Text to Numerical Features</h2>
<p>Machine learning algorithms work with numbers, not text. We need to transform our cleaned text into a numerical representation.</p>
<p><strong>TF-IDF (Term Frequency-Inverse Document Frequency)</strong> is a great choice for this. It assigns each word a score that reflects how important it is to a particular document relative to the entire dataset. A word that appears often in one email but rarely across all emails gets a high score — meaning it's distinctive and likely meaningful. Common words that appear everywhere get a lower score.</p>
<p><code>TfidfVectorizer</code> from scikit-learn handles this transformation. The parameters we set control what gets included:</p>
<ul>
<li><p><code>max_features=2500</code> — only keeps the 2,500 most frequent words, discarding rare ones that don't generalize well</p>
</li>
<li><p><code>min_df=5</code> — ignores words that appear in fewer than 5 emails (too rare to be useful)</p>
</li>
<li><p><code>max_df=0.7</code> — ignores words that appear in more than 70% of all emails (too common to be distinctive)</p>
</li>
<li><p><code>stop_words=stopwords.words('english')</code> — removes common English words like "the" and "is"</p>
</li>
</ul>
<p><code>fit_transform()</code> does two things in one step: it learns the vocabulary from our text (fit), then converts each email into a numerical vector based on that vocabulary (transform). Calling <code>.toarray()</code> on the result converts the sparse matrix output — which stores only non-zero values for efficiency — into a regular dense NumPy array that scikit-learn classifiers expect.</p>
<pre><code class="language-python">vectorizer = TfidfVectorizer(
    max_features=2500,
    min_df=5,
    max_df=0.7,
    stop_words=stopwords.words('english')
)

X = vectorizer.fit_transform(X_sentences).toarray()
</code></pre>
<p>Each email is now represented as a vector of 2,500 numbers, where each number is the TF-IDF score for a specific word.</p>
<h2 id="heading-how-to-train-the-naive-bayes-classifier">How to Train the Naive Bayes Classifier</h2>
<p>Now comes the exciting part — training our model! First, split the data into training and test sets using <code>train_test_split()</code>. This function randomly shuffles and divides both <code>X</code> and <code>y</code> simultaneously, keeping labels aligned with their corresponding emails. Setting <code>test_size=0.20</code> reserves 20% of the data for testing. Setting <code>random_state=42</code> seeds the random number generator so you get the same split every time you run the code, making your results reproducible.</p>
<pre><code class="language-python">X_train, X_test, y_train, y_test = train_test_split(
    X, y,
    test_size=0.20,
    random_state=42
)
</code></pre>
<p>Now train the Multinomial Naive Bayes classifier. We use <code>MultinomialNB</code> specifically because it's designed for features that represent counts or frequencies — exactly what TF-IDF scores are. Calling <code>fit(X_train, y_train)</code> trains the model by having it calculate the probability of each word appearing in spam versus legitimate emails across the training set. Those probability tables are what the model uses later to classify new emails.</p>
<pre><code class="language-python">
spam_detector = MultinomialNB()
spam_detector.fit(X_train, y_train)
</code></pre>
<p>That's it! The Naive Bayes algorithm is remarkably fast—training completes in milliseconds even with thousands of emails.</p>
<h2 id="heading-how-to-evaluate-model-performance">How to Evaluate Model Performance</h2>
<p>Let's see how well our spam detector performs on emails it has never seen before. The <code>predict()</code> method takes the test set features and returns a predicted label (0 or 1) for each email, based on the probability tables the model learned during training.</p>
<pre><code class="language-python">
y_pred = spam_detector.predict(X_test)
</code></pre>
<p>Now evaluate the predictions using three different tools from scikit-learn's <code>metrics</code> module:</p>
<ul>
<li><p><code>confusion_matrix()</code> — produces a 2×2 grid comparing actual vs. predicted labels, showing exactly where the model gets things right and wrong</p>
</li>
<li><p><code>classification_report()</code> — prints precision, recall, and F1-score for each class, giving a more complete picture than accuracy alone</p>
</li>
<li><p><code>accuracy_score()</code> — returns the overall percentage of correct predictions</p>
</li>
</ul>
<pre><code class="language-python">
print(confusion_matrix(y_test, y_pred))
print(classification_report(y_test, y_pred))
print(accuracy_score(y_test, y_pred))
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-plaintext">[[849   7]
 [ 18 272]]

              precision    recall  f1-score   support

           0       0.98      0.99      0.99       856
           1       0.97      0.94      0.96       290

    accuracy                           0.98      1146
   macro avg       0.98      0.96      0.97      1146
weighted avg       0.98      0.98      0.98      1146

0.9781849912739965
</code></pre>
<p>Our model achieves <strong>97.82% accuracy</strong>! Let's break down what the confusion matrix tells us:</p>
<ul>
<li><p><strong>849</strong>: Legitimate emails correctly identified as legitimate (True Negatives)</p>
</li>
<li><p><strong>7</strong>: Legitimate emails incorrectly marked as spam (False Positives)</p>
</li>
<li><p><strong>18</strong>: Spam emails that slipped through as legitimate (False Negatives)</p>
</li>
<li><p><strong>272</strong>: Spam emails correctly caught (True Positives)</p>
</li>
</ul>
<p>The classification report shows:</p>
<ul>
<li><p><strong>For legitimate emails (class 0)</strong>: 98% precision, 99% recall</p>
</li>
<li><p><strong>For spam emails (class 1)</strong>: 97% precision, 94% recall</p>
</li>
</ul>
<p>These numbers are impressive, especially considering the simplicity of our approach.</p>
<h2 id="heading-how-to-test-on-individual-emails">How to Test on Individual Emails</h2>
<p>Let's verify our model works by testing it on a specific email. We'll first print the cleaned text at index 56 and its actual label to see what we're working with. Then we'll ask the model to predict it.</p>
<pre><code class="language-python">
print(X_sentences[56])
print(y[56])
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-plaintext">Subject localized software all languages available hello we would like to offer localized software versions german french spanish uk and many others aii iisted software is available for immediate downioad no need to wait week for cd deiivery just few exampies norton lnternet security pro windows xp professionai with sp fuil version corei draw graphics suite dreamweaver mx homesite inciudinq macromedia studio mx just browse our site and find any software you need in your native ianguaqe best reqards kayieen 
1
</code></pre>
<p>This is clearly a spam email trying to sell pirated software. The actual label is 1 (spam). Now pass this single email through the same pipeline — first transforming it into a TF-IDF vector using the already-fitted <code>vectorizer</code>, then calling <code>predict()</code> on the result. It's important to use the same vectorizer that was fitted on the training data, so the word-to-index mapping is consistent.</p>
<pre><code class="language-python">
print(spam_detector.predict(vectorizer.transform([X_sentences[56]])))
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="language-plaintext">[1]
</code></pre>
<p>The model correctly identifies this promotional email as spam.</p>
<h2 id="heading-key-takeaways">Key Takeaways</h2>
<ol>
<li><p><strong>Naive Bayes is powerful for text classification</strong> despite its simplifying assumptions. For spam detection, it achieves excellent accuracy with minimal computational cost.</p>
</li>
<li><p><strong>Text preprocessing matters</strong>. Removing noise (special characters, numbers, extra spaces) helps the algorithm focus on meaningful patterns.</p>
</li>
<li><p><strong>TF-IDF captures word importance effectively</strong>. It gives higher weight to distinctive words that help differentiate spam from legitimate emails.</p>
</li>
<li><p><strong>Always evaluate with multiple metrics</strong>. Accuracy alone can be misleading, especially with imbalanced datasets. Precision, recall, and F1-score give a complete picture.</p>
</li>
<li><p><strong>Start simple</strong>. Before reaching for complex deep learning models, try classical algorithms like Naïve Bayes. They're interpretable, fast, and often surprisingly effective.</p>
</li>
</ol>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Want to improve this spam detector further? Here are some ideas:</p>
<ul>
<li><p><strong>Experiment with different vectorizers</strong>: Try CountVectorizer or word embeddings (Word2Vec, GloVe)</p>
</li>
<li><p><strong>Handle class imbalance</strong>: Use techniques like SMOTE or adjust class weights</p>
</li>
<li><p><strong>Feature engineering</strong>: Add features like email length, number of links, or sender domain</p>
</li>
<li><p><strong>Try other algorithms</strong>: Compare with SVM, Random Forest, or gradient boosting</p>
</li>
<li><p><strong>Deploy the model</strong>: Build a simple API using Flask or FastAPI</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>You've built a spam email classifier that achieves over 97% accuracy using the Naïve Bayes algorithm. Along the way, you learned about text preprocessing, feature extraction with TF-IDF, and model evaluation techniques.</p>
<p>The beauty of this approach is its simplicity. With just a few dozen lines of code, you've created something that actually works—and now you understand the principles behind commercial spam filters.</p>
<p>Feel free to experiment with the code, try different parameters, and see how the results change. That's the best way to deepen your understanding.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><a href="https://www.amazon.com/dp/B08WK2HCWL">Python Machine Learning Workbook for Beginners: 10 Machine Learning Projects Explained from Scratch</a> by AI Publishing</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Algorithm Analysis Deep Dive ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever just memorized that an algorithm is O(n log n) without truly understanding why? Our new algorithms course on the freeCodeCamp.org YouTube channel will help you build a deep intuition for how algorithms work. This Algorithm Analysis Deep... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/algorithm-analysis-deep-dive/</link>
                <guid isPermaLink="false">688b9162ab0310c598dc3d01</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 31 Jul 2025 15:53:06 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753977160999/8386f8e7-8b1c-4851-8aba-6e27370a05fa.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever just memorized that an algorithm is <code>O(n log n)</code> without truly understanding why? Our new algorithms course on the freeCodeCamp.org YouTube channel will help you build a deep intuition for how algorithms work.</p>
<p>This Algorithm Analysis Deep Dive course is taught by Computer Science Professor Dr. Qiang Hao. It goes beyond surface-level rules to help you understand the core mathematical reasoning behind performance.</p>
<p>Here are a list of the key sections in the course:</p>
<ul>
<li><p>Introduction to time complexity</p>
</li>
<li><p>Time complexity analysis of insertion sort</p>
</li>
<li><p>Asymptotic analysis</p>
</li>
<li><p>Divide and conquer - Recurrence tree method</p>
</li>
<li><p>Divide and conquer - Master theorem</p>
</li>
<li><p>Probabilistic analysis - Quicksort</p>
</li>
<li><p>Probabilistic analysis - Average case and expected value</p>
</li>
<li><p>Heaps and heapsort</p>
</li>
<li><p>Hashtables</p>
</li>
<li><p>Binary search trees</p>
</li>
<li><p>Amortized analysis</p>
</li>
</ul>
<p>This course is designed to connect the dots between the code you write and the theory behind it. And you can get all the course materials, like quizzes, assignments, and solutions, from the companion GitHub repository to follow along and test your knowledge.</p>
<p>Watch the <a target="_blank" href="https://youtu.be/ku6HZ_k9qgY">full course on the freeCodeCamp.org YouTube channel</a> (6-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/ku6HZ_k9qgY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Data Structure and Algorithm Patterns for LeetCode Interviews ]]>
                </title>
                <description>
                    <![CDATA[ To get the best tech jobs, it can be helpful to understand how to apply data structures and algorithms to coding challenges. We just published a comprehensive course on the freeCodeCamp.org channel about data structures and algorithms. This course wi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/data-structure-and-algorithm-patterns-for-leetcode-interviews/</link>
                <guid isPermaLink="false">687fa4c693f63bc290c6ada1</guid>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 22 Jul 2025 14:48:38 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753195703148/03e55da6-8391-4f8a-9493-036abd0518d9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>To get the best tech jobs, it can be helpful to understand how to apply data structures and algorithms to coding challenges.</p>
<p>We just published a comprehensive course on the freeCodeCamp.org channel about data structures and algorithms. This course will help you prepare for coding interviews and strengthen your foundational programming skills. Sheldon Chi developed this course.</p>
<p>Sheldon will break down the most essential data structures and algorithmic patterns. This course will help you build your intuition for efficiency and help you recognize which patterns to apply and how to avoid brute force solutions. And each concept is taught step by step, with practical code walkthroughs and tips for common pitfalls.</p>
<p>Here is the full list of sections in this course:</p>
<ul>
<li><p>Array</p>
</li>
<li><p>String</p>
</li>
<li><p>Set</p>
</li>
<li><p>Control Flow &amp; Looping</p>
</li>
<li><p>Big O Notation</p>
</li>
<li><p>Hashmap</p>
</li>
<li><p>Hashmap practice problems</p>
</li>
<li><p>Two Pointers</p>
</li>
<li><p>Two Pointers practice problems</p>
</li>
<li><p>Sliding Window</p>
</li>
<li><p>Sliding Window practice problems</p>
</li>
<li><p>Binary Search</p>
</li>
<li><p>Binary Search practice problems</p>
</li>
<li><p>Breadth-First Search (BFS) on Trees</p>
</li>
<li><p>BFS on Graphs</p>
</li>
<li><p>BFS practice problems</p>
</li>
<li><p>Depth-First Search (DFS)</p>
</li>
<li><p>DFS on Graphs</p>
</li>
<li><p>DFS practice problems</p>
</li>
<li><p>Backtracking</p>
</li>
<li><p>Backtracking practice problems</p>
</li>
<li><p>Priority Queue/heap</p>
</li>
<li><p>Priority Queue/heap practice problems</p>
</li>
</ul>
<p>Watch the full course <a target="_blank" href="https://youtu.be/Z_c4byLrNBU">on the freeCodeCamp.org YouTube channel</a> (1-hour course).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Z_c4byLrNBU" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Work with Queues in TypeScript ]]>
                </title>
                <description>
                    <![CDATA[ A queue is a collection of items arranged in a First-In-First-Out (FIFO) order. This means that the first item added is the first to be removed, much like a supermarket line where customers are served in the order they arrive. In this hands-on tutor... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-work-with-queues-in-typescript/</link>
                <guid isPermaLink="false">6850919d88713cbf971283b0</guid>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yazdun ]]>
                </dc:creator>
                <pubDate>Mon, 16 Jun 2025 21:50:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750082265731/de8b778c-935d-4a38-a5ef-748896475327.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A queue is a collection of items arranged in a First-In-First-Out (FIFO) order. This means that the first item added is the first to be removed, much like a supermarket line where customers are served in the order they arrive.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749741091206/42a62a3c-cf1b-4e7a-b8ce-4209e13f70d3.png" alt="Diagram illustrating a queue. Items are added to the back through &quot;enqueue&quot; and removed from the front through &quot;dequeue.&quot; Arrows show the flow into and out of a rectangular box representing the queue." class="image--center mx-auto" width="2138" height="950" loading="lazy"></p>
<p>In this hands-on tutorial, you will learn how to implement queues in TypeScript using linked lists.</p>
<h2 id="heading-heres-what-well-cover">Here’s what we’ll cover</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-getting-started">Getting started</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-queues">What are Queues?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-linked-lists">What are Linked Lists?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-simple-queue">What is a Simple Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-circular-queue">What is a Circular Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-double-ended-queue">What is a Double Ended Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-priority-queue">What is a Priority Queue?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-queues-and-when-to-avoid-them">When to Use Queues (and When to Avoid Them)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ol>
<li><p><strong>TypeScript:</strong> You need to know <a target="_blank" href="https://www.freecodecamp.org/news/learn-typescript-with-react-handbook/">TypeScript basics</a>, such as interfaces, types, and classes.</p>
</li>
<li><p><strong>Algorithm fundamentals:</strong> You need a basic understanding of data structures and algorithms. For example, you should be comfortable analyzing time and space complexity using <a target="_blank" href="https://www.freecodecamp.org/news/big-o-cheat-sheet-time-complexity-chart/">Big-O notation.</a></p>
</li>
<li><p><strong>Linked Lists Data Structure:</strong> It's important to have a solid understanding of linked lists before starting this tutorial. I wrote a detailed <a target="_blank" href="https://www.freecodecamp.org/news/how-to-code-linked-lists-with-typescript-handbook">linked list tutorial</a> that you can use to learn about this data structure.</p>
</li>
</ol>
<h2 id="heading-getting-started">Getting Started</h2>
<p>To get started with this tutorial, you’ll use a playground project that’s designed to help you implement queues and follow each step hands-on.</p>
<p>Clone the project from the <a target="_blank" href="https://github.com/Yazdun/fcc-queues">GitHub repository and code along</a> with the tutorial.</p>
<p>The project structure is as follows:</p>
<pre><code class="lang-plaintext">.
├── index.ts
├── examples
│   ├── 01-linked-list.ts
│   ├── 02-simple-queue.ts
│   ├── 03-circular-queue.ts
│   ├── 04-double-ended-queue.ts
│   └── 05-priority-queue.ts
└── playground
    ├── 01-linked-list.ts
    ├── 02-simple-queue.ts
    ├── 03-circular-queue.ts
    ├── 04-double-ended-queue.ts
    └── 05-priority-queue.ts
</code></pre>
<p>Throughout the tutorial, you will use the <code>playground</code> directory to implement and test your code.</p>
<p>The <code>examples</code> directory contains the final version of each implementation. If you get stuck, you can look at these solutions as a last resort!</p>
<h2 id="heading-what-are-queues">What Are Queues?</h2>
<p>A queue is a data structure that manages items in a first-in, first-out (FIFO) order, where the first item added is the first removed.</p>
<p>For example, imagine a printer handling jobs. If you send three documents to print, the printer processes them in the order they arrive. The first document prints first, then the second, and finally the third.</p>
<p>In programming, queues help manage tasks that need to happen in order, such as:</p>
<ul>
<li><p>A web server queues incoming requests to process them one by one.</p>
</li>
<li><p>A chat app queues messages to send them in the order they’re typed.</p>
</li>
<li><p>A navigation app queues locations to explore a map level by level. (Breadth-First Search)</p>
</li>
</ul>
<p>There are four types of queues in a data structure:</p>
<ul>
<li><p><strong>Simple Queue</strong>: Adds items to the back and removes them from the front in first-in, first-out (FIFO) order.</p>
</li>
<li><p><strong>Circular Queue</strong>: It is similar to a simple queue, except the last element is connected to the first.</p>
</li>
<li><p><strong>Double-Ended Queue (Deque)</strong>: Allows adding or removing items from both front and back, like a bus stop line where people join or leave either end.</p>
</li>
<li><p><strong>Priority Queue</strong>: Processes items based on priority, not arrival order. Like a delivery app processes VIP orders before regular ones.</p>
</li>
</ul>
<p>Each of these queues has a set of operations for managing their items. In this tutorial, you will learn about the following common and widely used operations:</p>
<ul>
<li><p><strong>enqueue</strong>: Adds an item to the back of the queue, like a new customer joining the end of a ticket line.</p>
</li>
<li><p><strong>dequeue</strong>: Removes and returns the item at the front of the queue.</p>
</li>
<li><p><strong>getFront</strong>: Looks at the item at the front without removing it, like checking who’s first in line.</p>
</li>
<li><p><strong>getRear</strong>: Looks at the item at the back without removing it, like seeing who’s last in line.</p>
</li>
<li><p><strong>isEmpty</strong>: Checks if the queue has no items.</p>
</li>
<li><p><strong>isFull</strong>: Checks if the queue has reached its maximum size.</p>
</li>
<li><p><strong>peek</strong>: Same as <code>getFront</code>, views the front item without removing it, like a quick glance at the first task.</p>
</li>
<li><p><strong>size</strong>: Returns the number of items in the queue, like counting how many people are in line.</p>
</li>
</ul>
<p>Now that you know about queues and their main operations, let's get into the actual implementation and see how it looks in code.</p>
<p>There are a few different ways to implement queues, but in this tutorial, you will learn about <strong>linked list-based queues</strong>, which use a linked list to create the queues.</p>
<p>First, let's briefly learn about the linked list data structure and then move on to the queue implementation.</p>
<h2 id="heading-what-are-linked-lists">What Are Linked Lists?</h2>
<p>A linked list is a method of storing a collection of items where each item, known as a "node," contains two parts: the actual data and a reference (or pointer) to the next item in the list.</p>
<p>Unlike arrays, where all items are stored next to each other in memory, linked lists connect nodes using these references, like a chain.</p>
<p>Linked lists are used to implement queues because they allow efficient <strong>insertion at the end</strong> and <strong>removal from the front</strong>, which are the two main operations of a queue.</p>
<p>In a linked list-based queue, you can add a new node at the tail and remove one from the head in constant time (<code>O(1)</code>) without needing to shift elements, as you would in an array.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749741385495/1bfab581-481d-4108-9f48-bf93d9dcf4f1.png" alt="Diagram of a linked list with four nodes connected sequentially. Node 1 is labeled as the head and Node 4 as the tail." class="image--center mx-auto" width="2566" height="950" loading="lazy"></p>
<p>In this tutorial, you are going to use a specific type of linked list called <strong>Circular Doubly Linked List</strong>.</p>
<p>A circular doubly linked list is a type of linked list where each node connects to both the next and previous nodes, and the last node loops back to the first one to form a circle.</p>
<p>This means you can move through the list in both directions and never hit a dead end. This makes it easy to go forward or backward through nodes and helps avoid special cases like handling <code>null</code> at the ends.</p>
<p>In a circular doubly linked list, everything is connected in a loop, which simplifies certain queue operations and keeps things efficient.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749741872784/d01a9c89-945e-4b4a-acff-56b7e528ea7e.png" alt="Diagram showing a circular doubly linked list with five nodes labeled from Node 1 (head) to Node 5 (tail), connected in a loop." class="image--center mx-auto" width="2566" height="950" loading="lazy"></p>
<p>You can learn more about circular linked lists in my <a target="_blank" href="https://www.freecodecamp.org/news/how-to-code-linked-lists-with-typescript-handbook/#heading-what-is-a-circular-linked-list">Linked Lists Handbook</a>.</p>
<p>For this tutorial, I’ve already added a circular doubly linked list in <code>src/playground/01-linked-list.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/01-linked-list.ts</span>

<span class="hljs-comment">/**
 * Node for doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> NodeItem&lt;T&gt; {
  value: T;
  next: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
  prev: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">value: T</span>) {
    <span class="hljs-built_in">this</span>.value = value;
  }
}

<span class="hljs-comment">/**
 * Circular Doubly Linked List
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> LinkedList&lt;T&gt; {
  <span class="hljs-keyword">private</span> head: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
  <span class="hljs-keyword">private</span> tail: NodeItem&lt;T&gt; | <span class="hljs-literal">null</span> = <span class="hljs-literal">null</span>;
  <span class="hljs-keyword">private</span> currentSize: <span class="hljs-built_in">number</span> = <span class="hljs-number">0</span>;

  <span class="hljs-comment">/**
   * Add a new node to the front of the list
   * @param value The value to add
   */</span>
  prepend(value: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> NodeItem(value);
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
      newNode.next = newNode;
      newNode.prev = newNode;
    } <span class="hljs-keyword">else</span> {
      newNode.next = <span class="hljs-built_in">this</span>.head;
      newNode.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.head!.prev = newNode;
      <span class="hljs-built_in">this</span>.tail!.next = newNode;
      <span class="hljs-built_in">this</span>.head = newNode;
    }
    <span class="hljs-built_in">this</span>.currentSize++;
  }

  <span class="hljs-comment">/**
   * Add a new node to the back of the list
   * @param value The value to add
   */</span>
  append(value: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> NodeItem(value);
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-built_in">this</span>.head = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
      newNode.next = newNode;
      newNode.prev = newNode;
    } <span class="hljs-keyword">else</span> {
      newNode.next = <span class="hljs-built_in">this</span>.head;
      newNode.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.tail!.next = newNode;
      <span class="hljs-built_in">this</span>.head!.prev = newNode;
      <span class="hljs-built_in">this</span>.tail = newNode;
    }
    <span class="hljs-built_in">this</span>.currentSize++;
  }

  <span class="hljs-comment">/**
   * Remove and return the value from the front of the list
   * @returns The value at the head or undefined if empty
   */</span>
  deleteHead(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
    }
    <span class="hljs-keyword">const</span> value = <span class="hljs-built_in">this</span>.head!.value;
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.currentSize === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-built_in">this</span>.head!.next;
      <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
      <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
    }
    <span class="hljs-built_in">this</span>.currentSize--;
    <span class="hljs-keyword">return</span> value;
  }

  <span class="hljs-comment">/**
   * Remove and return the value from the back of the list
   * @returns The value at the tail or undefined if empty
   */</span>
  deleteTail(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>;
    }
    <span class="hljs-keyword">const</span> value = <span class="hljs-built_in">this</span>.tail!.value;
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.currentSize === <span class="hljs-number">1</span>) {
      <span class="hljs-built_in">this</span>.head = <span class="hljs-literal">null</span>;
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-literal">null</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-built_in">this</span>.tail = <span class="hljs-built_in">this</span>.tail!.prev;
      <span class="hljs-built_in">this</span>.tail!.next = <span class="hljs-built_in">this</span>.head;
      <span class="hljs-built_in">this</span>.head!.prev = <span class="hljs-built_in">this</span>.tail;
    }
    <span class="hljs-built_in">this</span>.currentSize--;
    <span class="hljs-keyword">return</span> value;
  }

  <span class="hljs-comment">/**
   * Get the value at the front without removing it
   * @returns The value at the head or undefined if empty
   */</span>
  getHead(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.head?.value;
  }

  <span class="hljs-comment">/**
   * Get the value at the back without removing it
   * @returns The value at the tail or undefined if empty
   */</span>
  getTail(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.tail?.value;
  }

  <span class="hljs-comment">/**
   * Check if the list is empty
   * @returns True if the list is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.currentSize === <span class="hljs-number">0</span>;
  }

  <span class="hljs-comment">/**
   * Get the current size of the list
   * @returns The number of nodes in the list
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.currentSize;
  }
}
</code></pre>
<p>In this module, you have a circular doubly linked list with 8 different methods that will make it easier to build queues later in the tutorial:</p>
<ul>
<li><p><code>prepend</code>: Adds a new value to the <strong>front</strong> of the list.</p>
</li>
<li><p><code>append</code>: Adds a new value to the <strong>end</strong> of the list.</p>
</li>
<li><p><code>deleteHead</code>: Removes and returns the value at the <strong>front</strong>.</p>
</li>
<li><p><code>deleteTail</code>: Removes and returns the value at the <strong>end</strong>.</p>
</li>
<li><p><code>getHead</code>: Returns the front value <strong>without removing it</strong>.</p>
</li>
<li><p><code>getTail</code>: Returns the end value <strong>without removing it</strong>.</p>
</li>
<li><p><code>isEmpty</code>: Checks whether the list has <strong>no items</strong>.</p>
</li>
<li><p><code>size</code>: Returns the <strong>number of items</strong> currently in the list.</p>
</li>
</ul>
<p>Now that your linked list is ready, let's begin creating your first queue!</p>
<h2 id="heading-what-is-a-simple-queue">What is a Simple Queue?</h2>
<p>A Simple Queue follows the basic FIFO rule: you’ll to add items to the back and remove them from the front.</p>
<p>It’s like a line of customers at a ticket counter, where the first person in line buys a ticket first.</p>
<p>To get started, open <code>src/playground/02-simple-queue.ts</code>, where you will find the placeholder for the Simple Queue with its methods:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/02-simple-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Simple Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SimpleQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  ...methods
}
</code></pre>
<p>At the core of this <code>SimpleQueue</code> class, you're using a circular doubly linked list to store the items, and optionally allowing a maximum size limit to control how big the queue can grow.</p>
<ul>
<li><p><code>private list: LinkedList&lt;T&gt;</code> is where the queue's data is stored. Instead of a simple array, you're using a custom linked list, which makes it efficient to add or remove items from either end. The linked list manages the data structure and allows you to focus on how the queue works.</p>
</li>
<li><p><code>private maxSize</code> is an optional limit for how many items the queue can hold. If not provided, the queue can grow as large as needed.</p>
</li>
<li><p>Then, the <code>constructor</code> method that runs when you create a new queue. It creates a new, empty linked list to hold the queue items.</p>
</li>
</ul>
<p>Now, let's implement the queue methods.</p>
<p>Open your code editor and update <code>src/playground/02-simple-queue.ts</code> with the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/02-simple-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Simple Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> SimpleQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the rear of the queue
   * @param item The element to add
   */</span>
  enqueue(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Queue is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.append(item);
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the front of the queue
   * @returns The element at the front or undefined if empty
   */</span>
  dequeue(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the front without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the rear without removing it
   * @returns The element at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail();
  }

  <span class="hljs-comment">/**
   * Check if the queue is empty
   * @returns True if the queue is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the queue is full
   * @returns True if the queue is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.maxSize !== <span class="hljs-literal">undefined</span> &amp;&amp; <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the front element without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the queue
   * @returns The number of elements in the queue
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>As you can see, the linked list greatly simplifies your queue implementation because it acts as the engine behind your queue.</p>
<p>Here's how your Simple Queue works:</p>
<ul>
<li><p><strong>isEmpty()</strong>: This method checks whether the queue contains any items. It calls the <code>isEmpty()</code> method on the linked list, which internally checks if the current size of the list is zero. If the list has no nodes, it returns <code>true</code>, indicating that the queue is empty. This is a basic utility method often used before attempting to dequeue or inspect the queue.</p>
</li>
<li><p><strong>isFull()</strong>: This method determines whether the queue has reached its capacity. It compares the current size of the linked list (via the <code>size()</code> method) to the optional <code>maxSize</code> value. If <code>maxSize</code> is defined and the size is equal to or greater than that limit, it returns <code>true</code>, indicating that no more items can be added. This is useful to prevent overflow in bounded queues.</p>
</li>
<li><p><strong>size()</strong>: This method returns the number of items currently stored in the queue. It directly calls the <code>size()</code> method of the linked list, which tracks how many nodes are present. This allows you to monitor queue usage and remaining capacity.</p>
</li>
<li><p><strong>enqueue()</strong>: This method adds a new item to the end (rear) of the queue. It first checks whether the queue is full by calling the <code>isFull()</code> method. If it is, the method throws an error. Otherwise, it appends the new item to the internal linked list using the <code>append()</code> method, which adds the new node to the tail of the circular doubly linked list.</p>
</li>
<li><p><strong>dequeue()</strong>: This method removes and returns the item at the front of the queue. It calls the <code>deleteHead()</code> method of the linked list, which removes the head node and updates the links of the surrounding nodes to maintain the circular structure. If the queue is empty, it returns <code>undefined</code>.</p>
</li>
<li><p><strong>getFront()</strong>: This method returns the value at the front of the queue without removing it. It uses the <code>getHead()</code> method of the linked list to retrieve the value of the head node. This operation does not modify the queue and is useful for previewing the next item to be dequeued.</p>
</li>
<li><p><strong>getRear()</strong>: This method returns the value at the rear of the queue without removing it. It uses the <code>getTail()</code> method of the linked list, which returns the value of the tail node. This helps you inspect the most recently added item without altering the queue.</p>
</li>
<li><p><strong>peek()</strong>: This method is an alias for <code>getFront()</code>. It returns the item at the front of the queue without removing it. Internally, it calls <code>getFront()</code> to get the head value. This is often used in queue APIs to check the next item in line.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749742108067/3f5aab62-8314-4889-925a-cb9d52d9a277.png" alt="Flowchart illustrating queue operations. The process starts with either an enqueue or dequeue operation. Enqueue checks if the queue is full: if yes, triggers an error; if no, it adds an element, updates the rear pointer, and ends. Dequeue checks if the queue is empty: if yes, triggers an error; if no, removes an element, updates the front pointer, and ends." class="image--center mx-auto" width="1848" height="1644" loading="lazy"></p>
<p>You’ve just implemented your first queue in TypeScript. To make sure that your implementation works correctly, run the following command in your terminal at the root of the project:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 02
</code></pre>
<p>If any of the tests fail, use the final example from <code>src/examples/02-simple-queue.ts</code> to debug the issue, and then run the tests again.</p>
<p>If all tests pass, you can proceed to the next section, where you'll implement a Circular Queue.</p>
<h2 id="heading-what-is-a-circular-queue">What is a Circular Queue?</h2>
<p>A <code>CircularQueue</code> is a fixed-size queue where the last position connects back to the first. This allows you to reuse space after removing items.</p>
<p>Imagine a buffet line with a limited number of plates: when someone takes a plate from the front, a new one is added at the back, using the same space again.</p>
<p>The <code>CircularQueue</code> is quite similar to the <code>SimpleQueue</code>, but it has a few unique differences.</p>
<p>Let’s modify <code>src/playground/03-circular-queue.ts</code> and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/03-circular-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Circular Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> CircularQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Required maximum size of the circular queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the rear of the queue
   * @param item The element to add
   */</span>
  enqueue(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Circular queue is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.append(item);
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the front of the queue
   * @returns The element at the front or undefined if empty
   */</span>
  dequeue(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the front without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the rear without removing it
   * @returns The element at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail();
  }

  <span class="hljs-comment">/**
   * Check if the queue is empty
   * @returns True if the queue is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the queue is full
   * @returns True if the queue is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the front element without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the queue
   * @returns The number of elements in the queue
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>This may look very similar to a <code>SimpleQueue</code>, but there are a few key differences:</p>
<ul>
<li><p><strong>Constructor Difference</strong>: Unlike the <code>SimpleQueue</code>, the <code>CircularQueue</code> <strong>requires</strong> a <code>maxSize</code> parameter during instantiation. This enforces a strict upper limit on how many elements can be in the queue at once.</p>
<p>  In contrast, <code>SimpleQueue</code> treats <code>maxSize</code> as optional and allows unbounded queues. By making the size mandatory, <code>CircularQueue</code> is better suited for fixed-size buffer scenarios where memory or resource control is important (for example, in real-time systems or caching).</p>
</li>
<li><p><strong>enqueue()</strong>: This method is almost identical to the one in <code>SimpleQueue</code>, but the key difference lies in the design intent. In <code>CircularQueue</code>, throwing an error when the queue is full is part of the contract and it assumes that you’re managing a fixed buffer.</p>
<p>  The circular nature comes into play conceptually: once full, no more data can enter unless older entries are removed, which mimics a circular overwrite mechanism (though this specific implementation doesn’t auto-overwrite).</p>
</li>
<li><p><strong>isFull()</strong>: This method behaves the same as in <code>SimpleQueue</code> when a <code>maxSize</code> is set, but in <code>CircularQueue</code>, it’s always applicable because <code>maxSize</code> is required. The consistent presence of a size limit makes the queue predictable and ideal for bounded use cases like streaming data and rate-limited processing.</p>
</li>
</ul>
<p>Now, let's test the implementation to see if it works:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 03
</code></pre>
<p>If any of the tests fail, use the final <code>/examples</code> directory to debug the issue.</p>
<p>If the tests pass, you'll be ready to move on to the next section, where you will learn about double-ended queues.</p>
<h2 id="heading-what-is-a-double-ended-queue">What is a Double Ended Queue?</h2>
<p>A double-ended queue (deque) lets you add or remove items from both the front and the back.</p>
<p>It’s like a line at a bus stop where people can join or leave from either end.</p>
<p>Let’s modify <code>src/playground/04-double-ended-queue.ts</code> and add the following code:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/04-double-ended-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Double-Ended Queue (Deque) implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Deque&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;T&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the deque
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;T&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the front of the deque
   * @param item The element to add
   */</span>
  enqueueFront(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Deque is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.prepend(item);
  }

  <span class="hljs-comment">/**
   * Add an element to the rear of the deque
   * @param item The element to add
   */</span>
  enqueueRear(item: T): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Deque is full"</span>);
    }
    <span class="hljs-built_in">this</span>.list.append(item);
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the front of the deque
   * @returns The element at the front or undefined if empty
   */</span>
  dequeueFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead();
  }

  <span class="hljs-comment">/**
   * Remove and return the element from the rear of the deque
   * @returns The element at the rear or undefined if empty
   */</span>
  dequeueRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteTail();
  }

  <span class="hljs-comment">/**
   * Get the element at the front without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead();
  }

  <span class="hljs-comment">/**
   * Get the element at the rear without removing it
   * @returns The element at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail();
  }

  <span class="hljs-comment">/**
   * Check if the deque is empty
   * @returns True if the deque is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the deque is full
   * @returns True if the deque is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.maxSize !== <span class="hljs-literal">undefined</span> &amp;&amp; <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the front element without removing it
   * @returns The element at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the deque
   * @returns The number of elements in the deque
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>Now, let's go through the methods:</p>
<ul>
<li><p><strong>enqueueFront()</strong>: This method allows adding an element to the <strong>front</strong> of the deque, unlike in <code>SimpleQueue</code> or <code>CircularQueue</code> which only support adding to the rear. Internally, it uses <code>list.prepend(item)</code> to insert the item at the head.</p>
<p>  This operation makes the deque suitable for use cases where elements need to be pushed and popped from both ends, like in undo/redo systems or task schedulers.</p>
</li>
<li><p><strong>enqueueRear()</strong>: This behaves similarly to <code>SimpleQueue</code>’s <code>enqueue</code>, adding elements to the <strong>rear</strong> using <code>list.append(item)</code>.</p>
<p>  The distinction in <code>Deque</code> is that this is just one of two symmetric operations and it gives you full double-ended control.</p>
</li>
<li><p><strong>dequeueFront()</strong>: This removes and returns the element from the <strong>front</strong> of the deque using <code>list.deleteHead()</code>.</p>
<p>  While similar to the <code>dequeue</code> method in queues, the naming here is explicit to clarify that it's operating on the front and can be paired with a rear counterpart.</p>
</li>
<li><p><strong>dequeueRear()</strong>: This is a unique feature to deques, it removes and returns the element at the <strong>rear</strong> using <code>list.deleteTail()</code>. This complements <code>dequeueFront()</code> and enables LIFO (stack-like) behavior if needed.</p>
</li>
<li><p><strong>Constructor Difference</strong>: Like <code>SimpleQueue</code>, the <code>Deque</code> accepts an optional <code>maxSize</code>. This allows for flexible configurations.</p>
<p>  You can have unbounded deques when <code>maxSize</code> is not provided, or fixed-size deques when constraints are important. This is in contrast to <code>CircularQueue</code>, which requires a max size.</p>
</li>
</ul>
<p>Once you have completed the implementation, run the following command to test the module:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 04
</code></pre>
<p>Now, you're ready to move on to the last section of the tutorial, where you'll learn about the Priority Queue.</p>
<h2 id="heading-what-is-a-priority-queue">What is a Priority Queue?</h2>
<p>A priority queue processes items based on their priority, not their order of arrival.</p>
<p>Higher-priority items are removed first, like an emergency room where patients with severe conditions are treated before others.</p>
<p>Let’s modify <code>src/playground/05-priority-queue.ts</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// 📁 src/playground/05-priority-queue.ts</span>

<span class="hljs-keyword">import</span> { LinkedList, NodeItem } <span class="hljs-keyword">from</span> <span class="hljs-string">"./01-linked-list"</span>;

<span class="hljs-comment">/**
 * Interface for an element with priority
 */</span>
<span class="hljs-keyword">interface</span> PriorityItem&lt;T&gt; {
  value: T;
  priority: <span class="hljs-built_in">number</span>;
}

<span class="hljs-comment">/**
 * Priority Queue implemented with a circular doubly linked list
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> PriorityQueue&lt;T&gt; {
  <span class="hljs-keyword">private</span> list: LinkedList&lt;PriorityItem&lt;T&gt;&gt;;
  <span class="hljs-keyword">private</span> maxSize?: <span class="hljs-built_in">number</span>;

  <span class="hljs-comment">/**
   * @param maxSize Optional maximum size of the priority queue
   */</span>
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params">maxSize?: <span class="hljs-built_in">number</span></span>) {
    <span class="hljs-built_in">this</span>.list = <span class="hljs-keyword">new</span> LinkedList&lt;PriorityItem&lt;T&gt;&gt;();
    <span class="hljs-built_in">this</span>.maxSize = maxSize;
  }

  <span class="hljs-comment">/**
   * Add an element to the queue based on its priority
   * Higher priority numbers are dequeued first
   * @param value The value to add
   * @param priority The priority of the value (higher number = higher priority)
   */</span>
  enqueue(value: T, priority: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">void</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isFull()) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Priority queue is full"</span>);
    }

    <span class="hljs-keyword">const</span> newItem: PriorityItem&lt;T&gt; = { value, priority };
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.isEmpty()) {
      <span class="hljs-built_in">this</span>.list.prepend(newItem);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">let</span> current = <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>];
    <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">while</span> (
      current &amp;&amp;
      current.value.priority &gt;= priority &amp;&amp;
      count &lt; <span class="hljs-built_in">this</span>.size()
    ) {
      current = current.next;
      count++;
    }

    <span class="hljs-keyword">if</span> (count === <span class="hljs-built_in">this</span>.size()) {
      <span class="hljs-built_in">this</span>.list.append(newItem);
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">const</span> newNode = <span class="hljs-keyword">new</span> NodeItem(newItem);
      newNode.next = current;
      newNode.prev = current!.prev;
      <span class="hljs-keyword">if</span> (current!.prev) {
        current!.prev.next = newNode;
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>] = newNode;
      }
      current!.prev = newNode;
      <span class="hljs-keyword">if</span> (current === <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>]) {
        <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>] = newNode;
      }
      <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"tail"</span>]!.next = <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>];
      <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"head"</span>]!.prev = <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"tail"</span>];
      <span class="hljs-built_in">this</span>.list[<span class="hljs-string">"currentSize"</span>]++;
    }
  }

  <span class="hljs-comment">/**
   * Remove and return the element with the highest priority from the queue
   * @returns The value with the highest priority or undefined if empty
   */</span>
  dequeue(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.deleteHead()?.value;
  }

  <span class="hljs-comment">/**
   * Get the element with the highest priority without removing it
   * @returns The value at the front or undefined if empty
   */</span>
  getFront(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getHead()?.value;
  }

  <span class="hljs-comment">/**
   * Get the element with the lowest priority without removing it
   * @returns The value at the rear or undefined if empty
   */</span>
  getRear(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.getTail()?.value;
  }

  <span class="hljs-comment">/**
   * Check if the queue is empty
   * @returns True if the queue is empty, false otherwise
   */</span>
  isEmpty(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.isEmpty();
  }

  <span class="hljs-comment">/**
   * Check if the queue is full
   * @returns True if the queue is full, false otherwise
   */</span>
  isFull(): <span class="hljs-built_in">boolean</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.maxSize !== <span class="hljs-literal">undefined</span> &amp;&amp; <span class="hljs-built_in">this</span>.list.size() &gt;= <span class="hljs-built_in">this</span>.maxSize;
  }

  <span class="hljs-comment">/**
   * Peek at the element with the highest priority without removing it
   * @returns The value at the front or undefined if empty
   */</span>
  peek(): T | <span class="hljs-literal">undefined</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.getFront();
  }

  <span class="hljs-comment">/**
   * Get the current size of the queue
   * @returns The number of elements in the queue
   */</span>
  size(): <span class="hljs-built_in">number</span> {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.list.size();
  }
}
</code></pre>
<p>Let's understand how the methods work within a Priority Queue:</p>
<ul>
<li><p><strong>enqueue()</strong>: This method inserts a new element into the queue based on its <code>priority</code>. Unlike other queue types where order is based on insertion time, <code>PriorityQueue</code> uses a sorting mechanism where elements with higher <code>priority</code> values are placed closer to the front.</p>
<p>  The method traverses the linked list from the head, searching for the correct position where the new item should be inserted so that the list remains sorted in descending priority order.</p>
<p>  It manually adjusts the <code>prev</code> and <code>next</code> pointers to keep the circular doubly linked list intact. This sorting during insertion ensures quick access to the highest priority element later.</p>
</li>
<li><p><strong>dequeue()</strong>: This method removes and returns the element with the highest priority, which is always positioned at the front of the list.</p>
<p>  Internally, it calls <code>deleteHead()</code> and then returns the <code>value</code> from the <code>PriorityItem&lt;T&gt;</code> node. Because items are sorted during insertion, this operation is always efficient and retrieves the correct item.</p>
</li>
<li><p><strong>getFront()</strong>: This retrieves the value at the front of the queue without removing it. Since the list is sorted in descending priority, this value always represents the highest priority item.</p>
</li>
<li><p><strong>getRear()</strong>: This returns the value at the rear of the queue, which is the item with the <strong>lowest</strong> priority. It accesses the last element in the list using <code>getTail()</code> and extracts the <code>value</code>.</p>
</li>
<li><p><strong>isEmpty()</strong>: This checks whether the queue contains any elements by delegating to the linked list’s <code>isEmpty()</code> method.</p>
</li>
<li><p><strong>isFull()</strong>: This checks whether the queue has reached its maximum allowed size. It compares the current size with <code>maxSize</code> if it's defined.</p>
</li>
<li><p><strong>peek()</strong>: This is functionally equivalent to <code>getFront()</code>. It provides a clearer semantic name when users want to examine the highest-priority element without removing it.</p>
</li>
<li><p><strong>size()</strong>: This returns the total number of items currently in the priority queue. It's useful for monitoring capacity or debugging.</p>
</li>
<li><p><strong>Key Differences</strong>: The priority queue differs from other queue types by enforcing order during insertion based on a numeric priority.</p>
<p>  This enables <strong>constant-time access to the highest priority element</strong> but introduces <strong>linear-time insertion</strong> complexity due to the need to find the correct place for each new element.</p>
<p>  It supports advanced scheduling and load balancing use cases where task urgency or importance matters more than arrival time.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749743948626/78505f93-d7fd-4c63-b59a-5db1edcdae6c.png" alt="Flowchart illustrating the process of inserting an element into a priority queue. It begins by checking if the queue is empty, then assesses priority, updates the queue, traverses it if necessary, and continually checks for the correct position to insert." class="image--center mx-auto" width="3026" height="1510" loading="lazy"></p>
<p>Once you’re done with the implementation, run the following command to test your code:</p>
<pre><code class="lang-bash">npm run <span class="hljs-built_in">test</span>:file 05
</code></pre>
<p>That’s it, congratulations!</p>
<p>You have successfully completed the tutorial and learned about queues and their different variations. Great job!</p>
<p>Before reaching conclusions, let’s briefly learn about where to use queues and where to avoid them. We’ll also discuss the bottlenecks and issues that queues may create if not used correctly and in the right place.</p>
<h2 id="heading-when-to-use-queues-and-when-to-avoid-them"><strong>When to Use Queues (and When to Avoid Them)</strong></h2>
<p>Queues are ideal in scenarios where tasks or data must be processed in the exact order they arrive, such as in job scheduling and event handling systems.</p>
<p>For example, when multiple print jobs are sent to a printer, a queue can make sure each document is printed in the order it was submitted.</p>
<p>Similarly, queues are used in operating systems for managing tasks in thread pools or CPU scheduling (for example, Round Robin), where order is crucial.</p>
<p>Queues are also heavily used in asynchronous communication systems such as message brokers like RabbitMQ and Kafka.</p>
<p>In these systems, producers and consumers operate independently: a producer pushes messages into the queue, and a consumer processes them later.</p>
<p>This pattern is extremely useful in microservices architecture or serverless environments, where different parts of a system need to remain loosely coupled and highly scalable.</p>
<p>Similarly, in real-time systems like video streaming or sensor data ingestion, queues help buffer incoming data to avoid data loss and allow for smooth downstream processing.</p>
<h3 id="heading-when-to-avoid-queues">When to Avoid Queues</h3>
<p>Queues are not well-suited for problems that require random access to elements, complex search operations, or sorting.</p>
<p>Since queues typically allow insertion at one end and removal from the other, they’re inefficient for use cases where you frequently need to access elements in the middle or search through all items.</p>
<p>An array, tree, or hash map would serve better in such cases.</p>
<p>Using queues inappropriately can introduce unnecessary complexity and hidden bottlenecks.</p>
<p>For instance, blindly placing a queue between every microservice might decouple components but also make debugging and failure handling more difficult.</p>
<p>Over-queuing can also lead to backpressure problems where queues grow uncontrollably under high load which will increase latency or even crashing the system if not managed properly.</p>
<p>So you should use queues deliberately: when order, buffering, or async processing is required.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Queues are a basic data structure that work well when you need order and async processing.</p>
<p>Queues are useful for handling tasks, streaming data, or coordinating services, and making sure things run smoothly and efficiently.</p>
<p>But they aren't suitable for every problem. It's important to understand their pros and cons to use them correctly and avoid unnecessary complexity.</p>
<p>Thanks for following along with this tutorial. You can follow me on <a target="_blank" href="https://x.com/Yazdun">X</a>, where I share more useful tips on data structures and web development.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Binary Exponentiation Algorithm – Explained with Practical Examples ]]>
                </title>
                <description>
                    <![CDATA[ Binary exponentiation, also known as exponentiation by squaring, is a powerful algorithm used to efficiently calculate large powers of numbers. This technique is particularly useful in various fields of computer science, including cryptography, compe... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/binary-exponentiation-algorithm-explained-with-examples/</link>
                <guid isPermaLink="false">670d739fdb0a005601d5afdc</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Competitive programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MathJax ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sahil ]]>
                </dc:creator>
                <pubDate>Mon, 14 Oct 2024 19:40:15 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1728672475917/5eeec863-5481-42d8-8b1f-9c92915f570f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Binary exponentiation, also known as exponentiation by squaring, is a powerful algorithm used to efficiently calculate large powers of numbers. This technique is particularly useful in various fields of computer science, including cryptography, competitive programming, and computer graphics.</p>
<p>In this article, we'll explore the concept of binary exponentiation, understand how it works, and implement it in code.</p>
<h2 id="heading-what-is-binary-exponentiation">What is Binary Exponentiation?</h2>
<p>Binary exponentiation is a method to compute \(a^n\) (a raised to the power of n) using only multiplications, instead of the naïve \(O(n)\) multiplications.</p>
<p>This significant improvement in efficiency makes it possible to calculate extremely large powers quickly, even when dealing with modular arithmetic.</p>
<h2 id="heading-how-binary-exponentiation-works">How Binary Exponentiation Works</h2>
<p>The key idea behind binary exponentiation is to break down the exponent into its binary representation and use the properties of exponents to simplify the calculation.</p>
<p>Let's break it down step by step:</p>
<ol>
<li><p>Convert the exponent <code>n</code> to its binary representation.</p>
</li>
<li><p>Initialize the result as 1 and the base as <code>a</code>.</p>
</li>
<li><p>Iterate through each bit of the binary representation of <code>n</code> from right to left: (a). If the current bit is 1, multiply the result by the current base. (b). Square the base (multiply it by itself).</p>
</li>
<li><p>Return the final result.</p>
</li>
</ol>
<p>For example, let's calculate \(3^{13}\):</p>
<ol>
<li><p>Convert 13 to binary: \(13_{10} = 1101_2\)</p>
</li>
<li><p>Initialize result = 1, base = 3</p>
</li>
<li><p>Iterate through the bits:</p>
<ul>
<li><p>Bit 1: result = \(1 *3 = 3\)<em>, base =</em> \(3 *3 = 9\)</p>
</li>
<li><p>Bit 0: result = 3, base = \(9 * 9 = 81\)</p>
</li>
<li><p>Bit 1: result = \(3 *81 = 243\)<em>, base =</em> \(81 *81 = 6561\)</p>
</li>
<li><p>Bit 1: result = \(243 * 6561 = 1,594,323\)</p>
</li>
</ul>
</li>
</ol>
<p>Thus, \(3^{13}=1,594,323.\)</p>
<h2 id="heading-why-binary-exponentiation-is-efficient">Why Binary Exponentiation is Efficient</h2>
<p>The efficiency of binary exponentiation comes from two main factors:</p>
<ol>
<li><p><strong>Reduced number of multiplications</strong>: Instead of performing <code>n-1</code> multiplications as in the naïve approach, we only perform \(O(log n)\) multiplications. This is because we're essentially breaking down the problem into smaller subproblems based on the binary representation of the exponent.</p>
</li>
<li><p><strong>Reuse of previous calculations</strong>: By squaring the base at each step, we're reusing the results of previous calculations, which significantly reduces the overall number of operations needed.</p>
</li>
</ol>
<p>To illustrate this efficiency, consider calculating \(a^{1000000}\). The naïve approach would require 999,999 multiplications, while binary exponentiation would only require about 20 multiplications (as \(\log_2(1000000) \approx 20\)).</p>
<h2 id="heading-algorithm-implementation">Algorithm Implementation</h2>
<p>Let's implement the binary exponentiation algorithm in Python:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_exponentiation</span>(<span class="hljs-params">base, exponent</span>):</span>
    result = <span class="hljs-number">1</span>
    <span class="hljs-keyword">while</span> exponent &gt; <span class="hljs-number">0</span>:
        <span class="hljs-comment"># If the current bit is 1, multiply the result by the current base</span>
        <span class="hljs-keyword">if</span> exponent &amp; <span class="hljs-number">1</span>:
            result *= base
        <span class="hljs-comment"># Square the base</span>
        base *= base
        <span class="hljs-comment"># Move to the next bit</span>
        exponent &gt;&gt;= <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> result

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

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

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

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

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

result = matrix_power(A, n, mod)
print(result)  <span class="hljs-comment"># Output: [[690749268 297612485]</span>
                <span class="hljs-comment">#         [297612485 393136783]]</span>
</code></pre>
<p><strong>Explanation</strong>:</p>
<ol>
<li><p><code>matrix_multiply(A, B, mod)</code>:</p>
<ul>
<li><p>This function performs matrix multiplication of two 2x2 matrices, A and B.</p>
</li>
<li><p>Each element of the resulting matrix is computed using the standard matrix multiplication formula, followed by a modulo operation to keep the values manageable.</p>
</li>
</ul>
</li>
<li><p><code>matrix_power(A, n, mod)</code>:</p>
<ul>
<li><p>This function implements binary exponentiation for matrices.</p>
</li>
<li><p>We start with <code>result</code> as the 2x2 identity matrix (created using <code>np.eye(2, dtype=int)</code>).</p>
</li>
<li><p>The main loop follows the same pattern as scalar binary exponentiation: a. If the current bit of n is 1, we multiply <code>result</code> by the current <code>A</code>. b. We square <code>A</code> (by multiplying it with itself). c. We right-shift n to move to the next bit.</p>
</li>
<li><p>All matrix multiplications are done using our <code>matrix_multiply</code> function, which incorporates modular arithmetic.</p>
</li>
</ul>
</li>
</ol>
<p>This matrix exponentiation technique is particularly powerful for solving linear recurrence relations in logarithmic time, as demonstrated here with the Fibonacci sequence.</p>
<h2 id="heading-practice-problems">Practice Problems</h2>
<p>Here are some problems for you to solve using binary exponentiation:</p>
<ol>
<li><p><strong>Modular Exponentiation</strong>: Calculate \(7^{1234567} \bmod 1000000009\). (Hint: Use the <code>mod_binary_exponentiation</code> function from Problem 1 in the examples.)</p>
</li>
<li><p><strong>Last Digit</strong>: Find the last digit of . (Hint: Observe the pattern of last digits of powers of 2 and use binary exponentiation with modulo 10.)</p>
</li>
<li><p><strong>Power Tower</strong>: Calculate the last 3 digits of \(2^{2^{20}}\). (Hint: Use the property of modular arithmetic that \(a^b \bmod m = a^{b \bmod \phi(m)} \bmod m\) where \(\phi\) is Euler's totient function. You'll need to calculate \(2^{20} \bmod \phi(1000)\) first.)</p>
</li>
<li><p><strong>Matrix Chains</strong>: Given a 2x2 matrix A = [[1, 2], [3, 4]], calculate the last two digits of the sum of all elements in \(A^{1000000}\). (Hint: Use matrix exponentiation as in Problem 2 from the examples, but only keep track of the last two digits of each element. You'll need to sum the elements after the final exponentiation.)</p>
</li>
<li><p><strong>Fibonacci Sequence</strong>: Find the 1000000th Fibonacci number modulo 1000000007. (Hint: Use the matrix form of the Fibonacci sequence ([[1, 1], [1, 0]]) and apply matrix exponentiation as shown in Problem 2 of the examples.)</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Binary exponentiation is a powerful technique that can be applied to a wide range of problems involving large exponents. As we've seen in the example and practice problems, it's particularly useful in modular arithmetic, matrix operations, and solving recurrence relations.</p>
<p>By practicing these problems, you'll gain a deeper understanding of how to apply binary exponentiation in various scenarios. Remember, the key is to recognize when a problem involves raising something to a large power, whether it's a number, a matrix, or even a more complex structure.</p>
<p>If you found this explanation of Binary Exponentiation algorithm helpful, you might also enjoy more in-depth programming tutorials and concepts I cover on my <a target="_blank" href="https://blog.theenthusiast.dev">blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Match Parentheses in JavaScript without Using Regex ]]>
                </title>
                <description>
                    <![CDATA[ While writing my Lisp interpreter (for the Scheme dialect, to be precise), I decided to include support for square brackets. I did this because some of the Scheme books use them interchangeably with parentheses. But I didn't want to make the parser t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-match-parentheses-in-javascript-without-using-regex/</link>
                <guid isPermaLink="false">66ba29031567ba6dc973f17e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ parsing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jakub T. Jankiewicz ]]>
                </dc:creator>
                <pubDate>Mon, 12 Aug 2024 15:23:47 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1723400046627/d6cdb4d5-9c6e-4ce0-92a4-1438e5c998e3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>While writing my <a target="_blank" href="https://lips.js.org/">Lisp interpreter</a> (for the Scheme dialect, to be precise), I decided to include support for square brackets. I did this because some of the Scheme books use them interchangeably with parentheses. But I didn't want to make the parser too complex, so I didn't check if the pair of brackets matched.</p>
<p>In my Lisp interpreter, the brackets could be mixed like this:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">let</span> [(<span class="hljs-name">x</span> <span class="hljs-number">10</span>])
  [+ x x)]
</code></pre>
<p>The above code is an example of an S-Expression where we have tokens, a sequence of characters with meaning (like name <code>let</code> or number <code>10</code>), and brackets/parentheses. However, the code is not valid because it mixes pairs of parentheses and brackets.</p>
<pre><code class="lang-lisp">(<span class="hljs-name">let</span> [(<span class="hljs-name">x</span> <span class="hljs-number">10</span>)]
  [+ x x])
</code></pre>
<p>This is the proper Lisp syntax (if brackets are supported), where opening parentheses always match closing parenthesis and opening brackets always match closing brackets.</p>
<p>In this article, I'll show you how you can detect if the input is the second valid S-Expression and not the first invalid S-Expression.</p>
<p>We will also handle cases like this:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">define</span> foo <span class="hljs-number">10</span>))))
</code></pre>
<p>In the code above, you see invalid syntax with more closing than opening parentheses.</p>
<p>So in simple terms, we will detect if pairs of opening and closing characters like <code>()</code>, <code>[]</code>, and <code>{}</code> match inside the string like <code>"[foo () {bar}]"</code>.</p>
<p>The solution to this problem can be useful when implementing a Lisp parser, but you can also use it for different purposes (like some kind of validation or part of a math expression evaluator). It's also a good exercise.</p>
<p><strong>NOTE</strong>: to understand this article and code, you don't need to know anything about Lisp. But if you want some more context, you can read this article: <a target="_blank" href="https://lips.js.org/docs/scheme-intro/what-is-lisp">What is Lisp and Scheme</a>?</p>
<h2 id="heading-pairing-with-the-stack-data-structure">Pairing with the Stack Data Structure</h2>
<p>You may think that the simplest way to solve this problem is using <a target="_blank" href="https://www.freecodecamp.org/news/regular-expressions-crash-course/">Regular Expressions (RegExp)</a>. It may be possible to use Regex for simple cases, but soon it will get too complex and have more problems than it solves.</p>
<p>Actually, the easiest way of pairing opening and closing characters is using the stack. Stack is the simplest data structure. We have two basic operations: push, for adding an item to the stack, and pop, for removing an item.</p>
<p>This works similarly to a stack of books. The last item that you put onto the stack will be the first one that you take out.</p>
<p>You can read more about this data structure from this article: <a target="_blank" href="https://www.freecodecamp.org/news/data-structures-101-stacks-696b3282980/">Data Structures 101: Stacks</a>.</p>
<p>With a stack, it's easier to process (parse) the characters, which have a beginning and end, like XML tags or simple parentheses.</p>
<p>For example, say we have this XML code:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">element</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">item</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">sub-item</span>&gt;</span>text<span class="hljs-tag">&lt;/<span class="hljs-name">sub-item</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">item</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">element</span>&gt;</span>
</code></pre>
<p>When we use the stack, the last tag we open (inner <code>&lt;sub-item&gt;</code> for example) will always be the first we need to close (if the XML is valid).</p>
<p>So if we use the stack, we can push the item <code>&lt;sub-item&gt;</code> when we open it, and when we need to close it we can pop it from the stack. We only need to make sure that the last item on the stack (which is always the opening tag) matches the closing one.</p>
<p>We will have exact same logic with parentheses.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1723399558190/e70c9542-dad5-4259-8109-0d198796e5b5.png" alt="Illustration of processing a sequence of xml tags with a stack" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Note that if we have XML self-closing tags, we can skip them since they are open and automatically closed.</p>
<p>Arrays in JavaScript have both methods (push and pop), so they can be used as a Stack. But it's more convenient to create an abstraction in the form of a class, so we can add additional methods like <code>top()</code> and <code>is_empty()</code> that are easier to read.</p>
<p>But even if we didn't add new methods, it's always better to create abstractions like this, because it makes the code simpler and easier to read.</p>
<p>Most developers know common data structures and will immediately recognize them and not need to think about them. The most important thing with programming is forgetting not related stuff that are required at any given moment. The human memory is limited and can only hold about 4±1 items at the same time. You can read more about <a target="_blank" href="https://en.wikipedia.org/wiki/Short-term_memory">short-term memory</a> on Wikipedia.</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Stack</span> </span>{
    #data;
    <span class="hljs-keyword">constructor</span>() {
        <span class="hljs-comment">// creating new empty array as hiden property</span>
        <span class="hljs-built_in">this</span>.#data = [];
    }
    push(item) {
        <span class="hljs-comment">// push method just use native Array::push()</span>
        <span class="hljs-comment">// and add the item at the end of the array</span>
        <span class="hljs-built_in">this</span>.#data.push(item);
    }
    len() {
        <span class="hljs-comment">// size of the Stack</span>
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.#data.length;
    }
    top() {
        <span class="hljs-comment">// sice the items are added at the end</span>
        <span class="hljs-comment">// the top of the stack is the last item</span>
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.#data[<span class="hljs-built_in">this</span>.len() - <span class="hljs-number">1</span>];
    }
    pop() {
        <span class="hljs-comment">// pop is similar to push and use native Array::pop()</span>
        <span class="hljs-comment">// it removes and returns the last item in array</span>
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.#data.pop();
    }
    is_empty() {
        <span class="hljs-comment">// this comment shortcut !0 is true</span>
        <span class="hljs-comment">// since 0 can is coerced to false</span>
        <span class="hljs-keyword">return</span> !<span class="hljs-built_in">this</span>.len();
    }
}
</code></pre>
<p>The above code uses <a target="_blank" href="https://www.freecodecamp.org/news/write-less-do-more-with-javascript-es6-5fd4a8e50ee2/">ES6 (ES2015)</a> class and ES2022 <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties">private</a><br><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties">properties</a>.</p>
<h2 id="heading-the-parentheses-matching-algorithm">The Parentheses Matching Algorithm</h2>
<p>Now I will describe the algorithm (steps) needed to parse the parentheses.</p>
<p>We need a loop that will go through each token – and it's best if all other tokens are removed before processing.</p>
<p>When we have an opening parenthesis, we need to push that element into the stack. When we have a closing parenthesis, we need to check if the last element on the stack matches the one we are processing.</p>
<p>If the element is matching, we remove it from the stack. If not, it means that we have messed up parentheses, and we need to throw an exception.</p>
<p>When we have a closing bracket, but there is nothing on the stack, we also need to throw an exception, because there is no opening parenthesis that matches the closing one we have.</p>
<p>After checking all the characters (tokens), if something is left of the stack, it means that we didn't close all the parentheses. But this case is ok, because the user may be in the process of writing. So in this case, we return <code>false</code>, not an exception.</p>
<p>If the stack is empty, we return <code>true</code>. This means that we have a complete expression. If this was an S-Expression, we could use the parser to process it, and we would not need to worry about invalid results (of course if the parser was correct).</p>
<h2 id="heading-the-source-code">The Source Code</h2>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanced</span>(<span class="hljs-params">str</span>) </span>{
    <span class="hljs-comment">// pairs of matching characters</span>
    <span class="hljs-keyword">const</span> maching_pairs = {
        <span class="hljs-string">'['</span>: <span class="hljs-string">']'</span>,
        <span class="hljs-string">'('</span>: <span class="hljs-string">')'</span>,
        <span class="hljs-string">'{'</span>: <span class="hljs-string">'}'</span>
    };
    <span class="hljs-keyword">const</span> open_tokens = <span class="hljs-built_in">Object</span>.keys(maching_pairs);
    <span class="hljs-keyword">const</span> brackets = <span class="hljs-built_in">Object</span>.values(maching_pairs).concat(open_tokens);
    <span class="hljs-comment">// we filter out what is not our matching characters</span>
    <span class="hljs-keyword">const</span> tokens = tokenize(str).filter(<span class="hljs-function"><span class="hljs-params">token</span> =&gt;</span> {
        <span class="hljs-keyword">return</span> brackets.includes(token);
    });
    <span class="hljs-keyword">const</span> stack = <span class="hljs-keyword">new</span> Stack();
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> token <span class="hljs-keyword">of</span> tokens) {
        <span class="hljs-keyword">if</span> (open_tokens.includes(token)) {
            stack.push(token);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!stack.is_empty()) {
             <span class="hljs-comment">// there are matching characters on the stack</span>
            <span class="hljs-keyword">const</span> last = stack.top();
            <span class="hljs-comment">// the last opening character needs to match</span>
            <span class="hljs-comment">// the closing bracket we have</span>
            <span class="hljs-keyword">const</span> closing_token = maching_pairs[last];
            <span class="hljs-keyword">if</span> (token === closing_token) {
                stack.pop();
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-comment">// the character don't match</span>
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Syntax error: missing closing <span class="hljs-subst">${closing_token}</span>`</span>);
            }
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// this case when we have closing token but no opening one,</span>
            <span class="hljs-comment">// becauase the stack is empty</span>
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Syntax error: not matched closing <span class="hljs-subst">${token}</span>`</span>);
        }
    }
    <span class="hljs-keyword">return</span> stack.is_empty();
}
</code></pre>
<p>The above code was implemented as part of my <a target="_blank" href="https://www.freecodecamp.org/news/s-expressions-in-javascript/">S-Expression parser</a>, but the only thing I've used from that article is a function <code>tokenize()</code> that splits the string into tokens (where a token is a single object like number 123 or a string <code>"hello"</code>). If you want to process just the characters, you can use <code>str.split('')</code>, so the tokens would be an array of characters.</p>
<p>The code is much simpler than the S-Expression parser because we don't need to process all the tokens. But when we use the <code>tokenize()</code> function from the above article, we will be able to test input like this:</p>
<pre><code class="lang-lisp">(<span class="hljs-name">this</span> <span class="hljs-string">"))))"</span>)
</code></pre>
<p>The full source code (including the <code>tokenize()</code> function) can be found on <a target="_blank" href="https://gist.github.com/jcubic/4dd735dc31829ee69ce30ea4640c6fd8">GitHub</a>.</p>
<h2 id="heading-summary">Summary</h2>
<p>You shouldn't even start processing expressions that have opening and closing characters with regular expressions. On StackOverflow there is this famous answer to this question:</p>
<p><a target="_blank" href="https://stackoverflow.com/a/1732454/387194">RegEx match open tags except XHTML self-contained tags</a></p>
<p>Matching parentheses presents exactly the same problem, as parsing HTML. As you can see from the above code, ⁣it's a simpler problem to solve if we use the stack.</p>
<p>It's possible that we could write a Regular Expression that would check if the sequence of characters has matching parentheses. But it would soon get complicated if we had strings as tokens (sequence of characters), as with S-Expressions, and parentheses inside those stings should be ignored. It turns out that the solution is rather simple if we use the proper tools.</p>
<p>Personally, I love Regular Expressions, but you always need to decide if they're the right tool for the job.</p>
<p><strong>NOTE</strong>: This article was based on an article in the Polish blog <a target="_blank" href="https://jcubic.pl/">Głównie JavaScript</a> (ang. Mostly JavaScript), with a title: <a target="_blank" href="https://jcubic.pl/2020/04/parowanie-nawiasow-javascript.html">Jak parować nawiasy lub inne znaki w</a><br><a target="_blank" href="https://jcubic.pl/2020/04/parowanie-nawiasow-javascript.html">JavaScript?</a></p>
<p>If you like this article, you may want to follow me on Social Media: (<a target="_blank" href="https://x.com/jcubic">Twitter/X</a> and/or <a target="_blank" href="https://www.linkedin.com/in/jakubjankiewicz/">LinkedIn</a>). You can also check my <a target="_blank" href="https://jakub.jankiewicz.org/">personal website</a> and my <a target="_blank" href="https://jakub.jankiewicz.org/blog/">new blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Comparable vs Comparator Interfaces in Java – Which Should You Use and When? ]]>
                </title>
                <description>
                    <![CDATA[ Sorting is a fundamental operation in programming, essential for organizing data in a specific order. In Java, built-in sorting methods provide efficient ways to sort primitive data types and arrays, making it easy to manage and manipulate collection... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/comparable-vs-comparator-explained-in-java/</link>
                <guid isPermaLink="false">66ba0e6e79b7f411df58dea3</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ashutosh Krishna ]]>
                </dc:creator>
                <pubDate>Tue, 23 Jul 2024 13:13:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/comparable-comparator.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Sorting is a fundamental operation in programming, essential for organizing data in a specific order. In Java, built-in sorting methods provide efficient ways to sort primitive data types and arrays, making it easy to manage and manipulate collections of data. For instance, you can quickly sort an array of integers or a list of strings using methods like <code>Arrays.sort()</code> and <code>Collections.sort()</code>. </p>
<p>However, when it comes to sorting custom objects, such as instances of user-defined classes, the built-in sorting methods fall short. These methods don't know how to order objects based on custom criteria. This is where Java's <code>Comparable</code> and <code>Comparator</code> interfaces come into play, allowing developers to define and implement custom sorting logic tailored to specific requirements.</p>
<p>In this blog post, we'll explore how to use the <code>Comparable</code> and <code>Comparator</code> interfaces to sort custom objects in Java. I'll provide examples to illustrate the differences and use cases for each approach, helping you master custom sorting in your Java applications.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-sorting-methods-for-primitive-types">Sorting Methods for Primitive Types</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-comparable-interface">How to Use the Comparable Interface</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-comparator-interface">How to Use the Comparator Interface</a></li>
<li><a class="post-section-overview" href="#heading-comparable-vs-comparator">Comparable vs Comparator</a></li>
<li><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></li>
</ul>
<h2 id="heading-sorting-methods-for-primitive-types">Sorting Methods for Primitive Types</h2>
<p>Java provides a variety of built-in sorting methods that make it easy to sort primitive data types. These methods are highly optimized and efficient, allowing you to sort arrays and collections with minimal code. For primitive types, such as integers, floating-point numbers, and characters, the <code>Arrays.sort()</code> method is commonly used.</p>
<h3 id="heading-how-to-use-the-arrayssort-method">How to Use the Arrays.sort() Method</h3>
<p>The <code>Arrays.sort()</code> method sorts the specified array into ascending numerical order. This method uses a dual-pivot quicksort algorithm, which is faster and more efficient for most data sets.</p>
<p>Let's look at an example of sorting an array of integers and characters using <code>Arrays.sort()</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.Arrays;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PrimitiveSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">int</span>[] numbers = { <span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span> };
        System.out.println(<span class="hljs-string">"Original array: "</span> + Arrays.toString(numbers));

        Arrays.sort(numbers);
        System.out.println(<span class="hljs-string">"Sorted array: "</span> + Arrays.toString(numbers));

        <span class="hljs-keyword">char</span>[] characters = { <span class="hljs-string">'o'</span>, <span class="hljs-string">'i'</span>, <span class="hljs-string">'e'</span>, <span class="hljs-string">'u'</span>, <span class="hljs-string">'a'</span> };
        System.out.println(<span class="hljs-string">"Original array: "</span> + Arrays.toString(characters));

        Arrays.sort(characters);
        System.out.println(<span class="hljs-string">"Sorted array: "</span> + Arrays.toString(characters));
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original array: [5, 3, 8, 2, 1]
Sorted array: [1, 2, 3, 5, 8]
Original array: [o, i, e, u, a]
Sorted array: [a, e, i, o, u]
</code></pre>
<h3 id="heading-how-to-use-the-collectionssort-method">How to Use the Collections.sort() Method</h3>
<p>The <code>Collections.sort()</code> method is used to sort collections such as <code>ArrayList</code>. This method is also based on the natural ordering of the elements or a custom comparator.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Collections;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CollectionsSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        ArrayList&lt;String&gt; wordsList = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        wordsList.add(<span class="hljs-string">"banana"</span>);
        wordsList.add(<span class="hljs-string">"apple"</span>);
        wordsList.add(<span class="hljs-string">"cherry"</span>);
        wordsList.add(<span class="hljs-string">"date"</span>);
        System.out.println(<span class="hljs-string">"Original list: "</span> + wordsList);

        Collections.sort(wordsList);
        System.out.println(<span class="hljs-string">"Sorted list: "</span> + wordsList);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-plaintext">Original list: [banana, apple, cherry, date]
Sorted list: [apple, banana, cherry, date]
</code></pre>
<h3 id="heading-limitations-with-custom-classes">Limitations with Custom Classes</h3>
<p>While Java's built-in sorting methods, such as <code>Arrays.sort()</code> and <code>Collections.sort()</code>, are powerful and efficient for sorting primitive types and objects with natural ordering (like <code>String</code>), they fall short when it comes to sorting custom objects. These methods do not inherently know how to order user-defined objects because there is no natural way for them to compare these objects.</p>
<p>For example, consider a simple <code>Person</code> class that has <code>name</code>, <code>age</code>, and <code>weight</code> attributes:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Person [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }
}
</code></pre>
<p>If we try to sort a list of <code>Person</code> objects using <code>Arrays.sort()</code> or <code>Collections.sort()</code>, we will encounter a compilation error because these methods do not know how to compare <code>Person</code> objects:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Person&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people);
        System.out.println(<span class="hljs-string">"Sorted people list: "</span> + people);
    }
}
</code></pre>
<p>Compilation Error:</p>
<pre><code class="lang-bash">java: no suitable method found <span class="hljs-keyword">for</span> sort(java.util.List&lt;tutorial.Person&gt;)
    method java.util.Collections.&lt;T&gt;sort(java.util.List&lt;T&gt;) is not applicable
      (inference variable T has incompatible bounds
        equality constraints: tutorial.Person
        lower bounds: java.lang.Comparable&lt;? super T&gt;)
    method java.util.Collections.&lt;T&gt;sort(java.util.List&lt;T&gt;,java.util.Comparator&lt;? super T&gt;) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ <span class="hljs-keyword">in</span> length))
</code></pre>
<p>The error occurs because the <code>Person</code> class does not implement the <code>Comparable</code> interface, and there is no way for the sorting method to know how to compare two <code>Person</code> objects.</p>
<p>To sort custom objects like <code>Person</code>, we need to provide a way to compare these objects. Java offers two main approaches to achieve this:</p>
<ol>
<li>Implementing the <code>Comparable</code> Interface: This allows a class to define its natural ordering by implementing the <code>compareTo</code> method.</li>
<li>Using the <code>Comparator</code> Interface: This allows us to create separate classes or lambda expressions to define multiple ways of comparing objects.</li>
</ol>
<p>We will explore both approaches in the upcoming sections, starting with the <code>Comparable</code> interface.</p>
<h2 id="heading-how-to-use-the-comparable-interface">How to Use the Comparable Interface</h2>
<p>Java provides a <code>Comparable</code> interface to define a natural ordering for objects of a user-defined class. By implementing the <code>Comparable</code> interface, a class can provide a single natural ordering that can be used to sort its instances. This is particularly useful when you need a default way to compare and sort objects.</p>
<h3 id="heading-overview">Overview</h3>
<p>The <code>Comparable</code> interface contains a single method, <code>compareTo()</code>, which compares the current object with the specified object for order. The method returns:</p>
<ul>
<li>A negative integer if the current object is less than the specified object.</li>
<li>Zero if the current object is equal to the specified object.</li>
<li>A positive integer if the current object is greater than the specified object.</li>
</ul>
<h3 id="heading-how-comparable-allows-for-a-single-natural-ordering-of-objects">How Comparable Allows for a Single Natural Ordering of Objects</h3>
<p>By implementing the <code>Comparable</code> interface, a class can ensure that its objects have a natural ordering. This allows the objects to be sorted using methods like <code>Arrays.sort()</code> or <code>Collections.sort()</code> without the need for a separate comparator.</p>
<p>Let's implement the <code>Comparable</code> interface in a new <code>PersonV2</code> class, comparing by age.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonV2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparable</span>&lt;<span class="hljs-title">PersonV2</span>&gt; </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PersonV2</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"PersonV2 [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compareTo</span><span class="hljs-params">(PersonV2 other)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.age - other.age;
    }
}
</code></pre>
<p>In this implementation, the <code>compareTo()</code> method compares the <code>age</code> attribute of the current <code>PersonV2</code> object with the <code>age</code> attribute of the specified <code>PersonV2</code> object by subtracting one age from the other. By using the expression <code>this.age - other.age</code>, we’re effectively implementing this logic as follows:</p>
<ul>
<li>If <code>this.age</code> is less than <code>other.age</code>, the result will be negative.</li>
<li>If <code>this.age</code> is equal to <code>other.age</code>, the result will be zero.</li>
<li>If <code>this.age</code> is greater than <code>other.age</code>, the result will be positive.</li>
</ul>
<p><strong>Note</strong>: We can also use <code>Integer.compare(this.age, other.age)</code> instead of performing the arithmetic operation manually.</p>
<p>Now that the <code>PersonV2</code> class implements the <code>Comparable</code> interface, we can sort a list of <code>PersonV2</code> objects using <code>Collections.sort()</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSortingV2</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;PersonV2&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people);
        System.out.println(<span class="hljs-string">"Sorted people list: "</span> + people);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original people list: [PersonV2 [name=Alice, age=30, weight=65.5 kgs], PersonV2 [name=Bob, age=25, weight=75.0 kgs], PersonV2 [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list: [PersonV2 [name=Bob, age=25, weight=75.0 kgs], PersonV2 [name=Alice, age=30, weight=65.5 kgs], PersonV2 [name=Charlie, age=35, weight=80.0 kgs]]
</code></pre>
<p>In this example, the <code>PersonV2</code> objects are sorted in ascending order of age using the <code>Collections.sort()</code> method, which relies on the natural ordering defined by the <code>compareTo()</code> method in the <code>PersonV2</code> class.</p>
<h3 id="heading-limitations-of-comparable">Limitations of Comparable</h3>
<p>While the <code>Comparable</code> interface provides a way to define a natural ordering for objects, it has several limitations that can restrict its use in practical applications. Understanding these limitations can help us determine when to use other mechanisms, such as the <code>Comparator</code> interface, to achieve more flexible sorting.</p>
<ul>
<li><strong>Single Natural Ordering</strong>: The primary limitation of <code>Comparable</code> is that it allows only one natural ordering for the objects of a class. When you implement <code>Comparable</code>, you define a single way to compare objects, which is used whenever the objects are sorted or compared. This can be restrictive if you need to sort objects in multiple ways.</li>
<li><strong>Inflexibility</strong>: If you need to sort objects by different attributes or in different orders, you will have to modify the class or create new implementations of <code>Comparable</code>. This inflexibility can lead to a proliferation of comparison methods and can make the code harder to maintain.</li>
<li><strong>Non-Adaptable</strong>: Once a class implements <code>Comparable</code>, the natural ordering is fixed and cannot be easily changed. For instance, if your <code>PersonV2</code> class initially sorts by age but later you need to sort by weight or name, you have to either change the <code>compareTo()</code> method or create a new version of the class.</li>
</ul>
<p>This is where the <code>Comparator</code> interface comes into play. To define multiple ways of comparing objects, we can use the <code>Comparator</code> interface, which we will explore in the next section.</p>
<h2 id="heading-how-to-use-the-comparator-interface">How to Use the Comparator Interface</h2>
<p>The <code>Comparator</code> interface in Java provides a way to define multiple ways of comparing and sorting objects. Unlike the <code>Comparable</code> interface, which allows only a single natural ordering, <code>Comparator</code> is designed to offer flexibility by allowing multiple sorting strategies. This makes it particularly useful for scenarios where objects need to be sorted in different ways.</p>
<h3 id="heading-overview-1">Overview</h3>
<p>The <code>Comparator</code> interface defines a single method, <code>compare()</code>, which compares two objects and returns:</p>
<ul>
<li>A negative integer if the first object is less than the second object.</li>
<li>Zero if the first object is equal to the second object.</li>
<li>A positive integer if the first object is greater than the second object.</li>
</ul>
<p>This method provides a way to define custom ordering for objects without modifying the class itself.</p>
<h3 id="heading-how-comparator-allows-for-multiple-ways-of-ordering-objects">How Comparator Allows for Multiple Ways of Ordering Objects</h3>
<p>The <code>Comparator</code> interface allows you to create multiple <code>Comparator</code> instances, each defining a different ordering for objects. This flexibility means that you can sort objects by various attributes or in different orders without altering the object's class.</p>
<p>Let's implement multiple <code>Comparator</code> instances for the <code>Person</code> class. We'll define comparators for sorting by name, by age, and by weight. First, we need to update the <code>Person</code> class to include getters and ensure that attributes are accessible.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getWeight</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Person [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }
}
</code></pre>
<h4 id="heading-comparator-by-name"><strong>Comparator by Name</strong></h4>
<p>This comparator sorts <code>Person</code> objects alphabetically by their <code>name</code>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonNameComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> p1.getName().compareTo(p2.getName());
    }
}
</code></pre>
<h4 id="heading-comparator-by-age">Comparator by Age</h4>
<p>This comparator sorts <code>Person</code> objects by their <code>age</code>, in ascending order.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonAgeComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> p1.getAge() - p2.getAge();
    }
}
</code></pre>
<h4 id="heading-comparator-by-weight">Comparator by Weight</h4>
<p>This comparator sorts <code>Person</code> objects by their <code>weight</code>, in ascending order.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonWeightComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>) (p1.getWeight() - p2.getWeight());
    }
}
</code></pre>
<p>Now, here’s how you can use these <code>Comparator</code> instances to sort a list of <code>Person</code> objects:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> tutorial.comparator.PersonAgeComparator;
<span class="hljs-keyword">import</span> tutorial.comparator.PersonNameComparator;
<span class="hljs-keyword">import</span> tutorial.comparator.PersonWeightComparator;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSortingV3</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Person&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonNameComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by name: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonAgeComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by age: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonWeightComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by weight: "</span> + people);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original people list: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by name: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by age: [Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by weight: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
</code></pre>
<p>In this example, the <code>Comparator</code> instances allow sorting the <code>Person</code> objects by different attributes: name, age, and weight. This demonstrates how the <code>Comparator</code> interface enables flexible and versatile sorting strategies for a class.</p>
<h2 id="heading-comparable-vs-comparator">Comparable vs Comparator</h2>
<p>When sorting objects in Java, you have two primary options: the <code>Comparable</code> and <code>Comparator</code> interfaces. Understanding the differences between these two interfaces can help you choose the right approach for your needs. Please note that this is also a very important interview question.</p>
<h3 id="heading-comparison">Comparison</h3>
<p>Here’s a table comparing and contrasting the <code>Comparable</code> and <code>Comparator</code> interfaces in Java:</p>
<table><tbody><tr><th><p>Feature</p></th><th><p>Comparable</p></th><th><p>Comparator</p></th></tr><tr><td><p>Definition</p></td><td><p>Provides a single, natural ordering for objects</p></td><td><p>Provides multiple ways to compare objects</p></td></tr><tr><td><p>Method</p></td><td><p>compareTo(T o)</p></td><td><p>compare(T o1, T o2)</p></td></tr><tr><td><p>Implementation</p></td><td><p>Implemented within the class itself</p></td><td><p>Implemented outside the class</p></td></tr><tr><td><p>Sorting Criteria</p></td><td><p>One default natural ordering</p></td><td><p>Multiple sorting criteria</p></td></tr><tr><td><p>Flexibility</p></td><td><p>Limited to one way of comparing objects</p></td><td><p>Flexible; multiple comparators can be defined</p></td></tr><tr><td><p>Class Modification</p></td><td><p>Requires modifying the class to implement <code>Comparable</code></p></td><td><p>Does not require modifying the class</p></td></tr><tr><td><p>Use Case</p></td><td><p>Use when there is a clear, natural ordering (e.g., sorting employees by ID)</p></td><td><p>Use when different sorting orders are needed or when you cannot modify the class</p></td></tr></tbody></table>

<h3 id="heading-benefits-and-drawbacks-of-each-approach">Benefits and Drawbacks of Each Approach</h3>
<h4 id="heading-comparable-operator">Comparable Operator</h4>
<h5 id="heading-benefits">Benefits:</h5>
<ul>
<li><strong>Simplicity</strong>: Provides a default sorting order that is easy to implement and use.</li>
<li><strong>Built-in</strong>: The natural ordering is part of the class itself, so it is always available and used by default in sorting methods.</li>
</ul>
<h4 id="heading-drawbacks">Drawbacks:</h4>
<ul>
<li><strong>Single Ordering</strong>: Can only define one way to compare objects. If different sorting orders are needed, the class must be modified or additional <code>Comparator</code> instances must be used.</li>
<li><strong>Class Modification</strong>: Requires altering the class to implement <code>Comparable</code>, which might not be feasible if the class is part of a library or if its natural ordering is not clear.</li>
</ul>
<h4 id="heading-comparator">Comparator</h4>
<h5 id="heading-benefits-1">Benefits:</h5>
<ul>
<li><strong>Flexibility</strong>: Allows for multiple sorting orders and criteria, which can be defined externally and used as needed.</li>
<li><strong>Non-invasive</strong>: Does not require modification of the class itself, making it suitable for classes you do not control or when you need different sorting options.</li>
</ul>
<h5 id="heading-drawbacks-1">Drawbacks:</h5>
<ul>
<li><strong>Complexity</strong>: Requires creating and managing multiple <code>Comparator</code> instances, which can add complexity to the code.</li>
<li><strong>Overhead</strong>: Might introduce additional overhead if many comparators are used, especially if they are created on the fly.</li>
</ul>
<p>In summary, <code>Comparable</code> is best used when a class has a natural ordering that makes sense for most use cases. </p>
<p><code>Comparator</code>, on the other hand, provides flexibility for sorting by multiple criteria and is useful when the class does not have a natural ordering or when different sorting orders are needed. </p>
<p>Choosing between <code>Comparable</code> and <code>Comparator</code> depends on your specific sorting needs and whether you need a single default order or multiple flexible sorting options.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Understanding and utilizing both <code>Comparable</code> and <code>Comparator</code> can significantly enhance your ability to manage and manipulate object collections in Java. By applying these concepts, you can create more flexible and powerful sorting mechanisms.</p>
<p>To solidify your understanding, try implementing both <code>Comparable</code> and <code>Comparator</code> in real-world scenarios. Experiment with different classes and sorting criteria to see how each approach works in practice.</p>
<h3 id="heading-links-to-official-java-documentation">Links to Official Java Documentation:</h3>
<ul>
<li><a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html">Java Comparable Interface</a></li>
<li><a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html">Java Comparator Interface</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Rust Tutorial – Learn Multi-Scale Processing of Astronomical Images ]]>
                </title>
                <description>
                    <![CDATA[ Recently, there's been a massive amount of effort put into developing novel image processing techniques. And many of them are derived from digital signal processing methods such as Fourier and Wavelet transforms.  These techniques have not only enabl... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/multi-scale-analysis-of-images-in-rust/</link>
                <guid isPermaLink="false">66bb5795f55324ca867c88e2</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ image processing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rust ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anshul Sanghi ]]>
                </dc:creator>
                <pubDate>Wed, 10 Apr 2024 15:48:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/Watermark.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Recently, there's been a massive amount of effort put into developing novel image processing techniques. And many of them are derived from digital signal processing methods such as Fourier and Wavelet transforms. </p>
<p>These techniques have not only enabled a wide range of image processing techniques such as noise reduction, sharpening, and dynamic-range extension, but have also enabled many techniques used in compute vision such as edge detection, object detection, and so on.</p>
<p>Multi-scale analysis is one of the newer techniques (relatively speaking) that has been adopted in a wide range of applications, especially in the astronomical image and data processing applications. This technique, which is based on Wavelet transform, allows us to divide our data into multiple signals, that all add up to make the final signal. </p>
<p>We can then perform our processing or analysis work on this individual sub-signals, allowing us to do targeted operations that do not affect other sub-signals. </p>
<p>In this tutorial, we'll first be exploring what the technique is all about, through the lens of a particular algorithm for performing multi-scale analysis on images. We'll then move on to looking at how we can implement what we discussed in the first part in Rust programming language and recreate the examples you see in the first half of the article.</p>
<h2 id="heading-before-you-read">Before You Read:</h2>
<h3 id="heading-prerequisites-for-part-1">Prerequisites for Part 1:</h3>
<p>The technique described is derived from the concept of "Wavelet Transforms". You don't need to know everything about it, but a very basic understanding will help you grasp the material better.</p>
<p>Since the article focuses on image processing and analysis, a basic understanding of how pixels work in digital format is helpful, but not mandatory.</p>
<h3 id="heading-prerequisites-for-part-2">Prerequisites for Part 2:</h3>
<p>Here, we focus on implementing the algorithm using the Rust programming language, without going much into the details of the language itself. So being comfortable writing Rust programs, and comfortable reading crate documentations is required.</p>
<p>If this is not you, you can still read Part 1 and learn the technique, and then maybe you'll want to then try it out in a language of your choice. If you're not familiar with Rust, I highly encourage you to learn the basics. <a target="_blank" href="https://www.freecodecamp.org/news/rust-in-replit/">Here's an interactive Rust course</a> that can get you started.</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-part-1-understanding-the-multi-scale-processing-technique-and-algorithm">Part 1: Understanding Multi-Scale Processing Technique And Algorithm</a><ol>
<li><a class="post-section-overview" href="#heading-what-is-multi-scale-image-processing">What is multi-scale image processing</a></li>
<li><a class="post-section-overview" href="#heading-the-a-trous-wavelet-transform">The <em>À Trous</em> Wavelet Transform</a></li>
<li><a class="post-section-overview" href="#heading-scaling-functions">Scaling Functions</a></li>
<li><a class="post-section-overview" href="#heading-convolution-pixels-at-each-scale">Convolution Pixels At Each Scale</a></li>
<li><a class="post-section-overview" href="#heading-handling-boundary-conditions">Handling Boundary Conditions</a> </li>
<li><a class="post-section-overview" href="#heading-computing-maximum-possible-scales-for-any-given-image">Computing Maximum Possible Scales For Any Given Image</a></li>
<li><a class="post-section-overview" href="#heading-closing-notes">Closing Notes</a></li>
</ol>
</li>
<li><a class="post-section-overview" href="#heading-part-2-how-to-implement-a-trous-tranform-in-rust">Part 2: How to Implement <em>À Trous</em> Tranform in Rust</a><ol>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-the-a-trous-transform">The <em>À Trous</em> Transform</a></li>
<li><a class="post-section-overview" href="#heading-iterators-and-the-a-trous-transform">Iterators And The <em>À Trous</em> Transform</a></li>
<li><a class="post-section-overview" href="#heading-convolution">Convolution</a></li>
<li><a class="post-section-overview" href="#heading-implementing-the-iterator">Implementing the Iterator</a></li>
<li><a class="post-section-overview" href="#heading-recomposition">Recomposition</a></li>
<li><a class="post-section-overview" href="#heading-using-the-a-trous-transform">Using The <em>À Trous</em> Transform</a></li>
<li><a class="post-section-overview" href="#heading-further-reading">Further Reading</a></li>
</ol>
</li>
<li><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></li>
</ol>
<h2 id="heading-part-1-understanding-the-multi-scale-processing-technique-and-algorithm">Part 1: Understanding the Multi-Scale Processing Technique and Algorithm</h2>
<p>So what do we mean when we talk about multi-scale processing or analysis of some data? Well, we usually mean breaking down the input data into multiple signals, each representing a particular scale of information. </p>
<p>Scale, when talking about image analysis, simply refers to the size of structures that we are looking at at any given time. It ignores everything else that's either smaller or larger than the current scale.</p>
<h3 id="heading-what-is-multi-scale-image-processing">What is multi-scale image processing?</h3>
<p>For images, "scales" generally refer to the size in pixels of various structures or details in the image. You'll be able to get an intuitive understanding by looking at the following example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/Processed.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Messier 33, AKA Triangulum Galaxy</em></p>
<p>Assuming our naïve understanding is correct, we can derive images of at-least the following 3 scales:</p>
<ul>
<li>Very small structures, usually the size of a single pixel. This layer, when separated from the rest of the image, will only contain the noise and some sharp stars for the most part.</li>
<li>Small structures, usually a few pixels in size. This layer, when separated, will contain all of the stars and the very fine details in the galaxy arms.</li>
<li>Large and very large scale structures, usually 100s of pixels in size. This layer, when separated, will contain the general size and shape of the galaxy at the center.</li>
</ul>
<p>Now the question becomes, <strong>why do we need to do all of this in the first place?</strong></p>
<p>The answer is simple: it allows us to make targeted enhancements and changes to an image. </p>
<p>For example, noise reduction on the overall image will usually result in a loss of sharpness in the galaxy. But since we have broken our image down into multiple scales, we can easily apply noise reduction to only the first few layers, as most of the random noise that is easy to remove resides only in lower scale layers. </p>
<p>We then re-combine the noise-reduced low-scale layers with unmodified large-scale ones, and we have an output that gives us noise reduction without a loss in quality.</p>
<p>Another peculiar thing about noise is that it's almost always present in just one of these layers, making noise reduction process both easy and non-destructive.</p>
<p>If you're more of a visual learner, let's see this in practice using the image we used above. We're gonna be working with the following grayscale version of that image, where I've also added random gaussian noise:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/m33-noise-lum-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Messier 33 AKA Triangulum Galaxy, Converted to grayscale and with added Gaussian noise</em></p>
<p>Performing scale-based layer separation on this image, we get the following results. Note that the results are rescaled to a range where they can be viewed as an image for representational purpose. The actual transform produces pixel values that don't make sense when looked at independently, but all of the techniques and calculations described in this tutorial can still be safely applied without rescale. The recomposition process automatically gives us back the correct range:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/trous-decomposition..jpg" alt="Image" width="600" height="400" loading="lazy">
<em>9-level À Trous Decomposition. From top-left to bottom-right, we have images at the following pixel scales: 1, 2 4, 8, 16, 32, 64, 128, 256 (powers of 2)</em></p>
<ol>
<li>The first and second layers contain the noise and stars. In this particular example, noise is mixed in with the stars. But using the first and second layers, we can easily target areas that are not present in the second layer, as we can be sure that those are where the noise is present in the first layer.</li>
<li>With the third layer, we still see the residue luminance from stars. But if you look closely, we also see very faintly the arms of the galaxy starting to appear.</li>
<li>From the fourth layer onwards, we see the galaxy at varying scales and detail levels, completely without the stars. We start with the finer details (relatively small scale details) and increasingly move on to larger and larger scale samples. By the end, we only see a vague shape where the galaxy used to be.</li>
</ol>
<p>From here on, we can selectively apply noise reduction to the first two layers. Then we can recombine all of the layers to create the following image that has very little noise while preserving the same amount of details in the stars and the galaxy arms:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/wavelet-processed.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Messier 33 AKA Triangulum Galaxy, result of recombining all layers but with noise reduction applied to the pixel scale 1 &amp; 2 layers</em></p>
<p>In its most basic form, multi-scale analysis involves breaking up your source image, commonly referred to as the "signal", into multiple "signals" – each containing the data for a particular scale in the source signal. </p>
<p>Scale, when talking about image signal here, refers to the distance between adjacent pixels that we take when creating the layer from the source image.</p>
<p>In practice, this technique is used as the one of the first steps in all kinds of astronomical data analysis and image processing. </p>
<p>As an example, you can use the technique to detect locations of stars while ignoring larger structures much more easily than would be possible otherwise.</p>
<h3 id="heading-the-a-trous-wavelet-transform">The <em>À Trous</em> Wavelet Transform</h3>
<p>All of what I've showed you previously, and all of what you're going to see in this tutorial, was achieved with wavelet decomposition and recomposition using the à <em>trous</em> algorithm for discreet wavelet transforms.</p>
<p>This algorithm has been used throughout the years for various applications. But it's become particularly important recently in astronomical image processing applications, where different objects and signals in an image can be completely separated based on structural scales.</p>
<p>Here's how the algorithm works:</p>
<ol>
<li>We start with the source image input and number of levels to decompose into n.</li>
<li>For each level n:<ul>
<li>We convolve the image with our scaling function (we'll see what this is in a bit), where adjacent pixels are considered to be <strong>2<sup>n</sup></strong> units apart from each other, giving us the result <strong>result<sub>n</sub></strong>. This is where the "À Trous" name comes from, which literally translates to "with holes".</li>
<li>The layer output <strong>output<sub>n</sub></strong> is then computed using <strong>input</strong> - <strong>result<sub>n</sub></strong>.</li>
<li>We then update <strong>input</strong> to equal <strong>result<sub>n</sub></strong>. This is also known as residue data which serves as the source data for next layer.</li>
</ul>
</li>
<li>Repeat the above steps for all levels.</li>
<li>In the end, we have 9 wavelet layers, and 1 residue layer. All 10 layers are required for the recomposition.</li>
</ol>
<p>For a more mathematical approach to understanding this algorithm, I encourage you to read about <a target="_blank" href="https://www.eso.org/sci/software/esomidas/doc/user/18NOV/volb/node317.html"><strong>the à trous algorithm here</strong></a><strong>.</strong> </p>
<p>The recomposition process is very straightforward: we just need to add all 10 layers together. We can chose to apply positive or negative <strong>bias</strong> to any of the layers, which is a factor by which to multiply the layer pixel values during recomposition. You can use it either to enhance or diminish the characteristics of that particular layer.</p>
<h3 id="heading-scaling-functions">Scaling Functions</h3>
<p>Scaling functions are specific <a target="_blank" href="https://en.wikipedia.org/wiki/Kernel_(image_processing)">convolution kernels</a> that help us better represent data at a particular scale based on our use case. There are 3 most commonly used scaling functions, which are shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/b3spline-level2.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/linear-level2.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/low-scale-level2.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The images above show the 3 most commonly used scaling functions in the À Trous algorithm, visualised using 3rd level decomposition of the triangulum galaxy image used previously:</p>
<ul>
<li>B3 Spline is a very smooth kernel. It is mostly used in isolation of large scale structures. If we wanted to sharpen our galaxy, we would have used this kernel.</li>
<li>Low-scale is a very sharply peaked kernel, and is best at working with small scale structures.</li>
<li>Linear interpolation kernel gives us the best of both worlds, and hence is used when we need to work with both small scale and large scale structures. This is what we have used in all of our previous examples.</li>
</ul>
<h3 id="heading-convolution-pixels-at-each-scale">Convolution Pixels At Each Scale</h3>
<p>I mentioned in the algorithm that at each scale, the pixels in the image are considered to be 2<sup>n</sup> units apart. Let's try to grasp a better understanding of this using the following visualisation:</p>
<p>Consider the following 8px by 8px image. Each pixel is labeled 1 through 64, which is their index.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/1-32x32mm.png" alt="Image" width="600" height="400" loading="lazy">
<em>A representational pixel grid of a 8x8px image</em></p>
<p>We're going to focus on a convolution operation of one of the center pixels only for this example, let's say pixel number 28.</p>
<p><strong>Scale 0:</strong> At scale 0, the value of 2<sup>n</sup> becomes <strong>1</strong>. This means that for convolution, we'll consider pixels that are 1 unit apart from our target center pixel. These pixels are highlighted below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/scale0-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>8x8px grid with pixels that are involved in convolution for pixel number 28 highlighted at scale 0</em></p>
<p><strong>Scale 1:</strong> This is where things get interesting. At scale 1, the value of 2<sup>n</sup> becomes <strong>2</strong>. This means that for convolution, we'll jump directly to pixels that are 2 locations apart from the target pixel:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/scale1-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>8x8px grid with pixels that are involved in convolution for pixel number 28 highlighted at scale 1</em></p>
<p>As you can see, we've created "holes" in our computation of the value of the target pixel by skipping <strong>2<sup>n</sup> - 1</strong> adjacent pixels and selecting the <strong>2<sup>n</sup>th</strong> pixel. This is the basis of the algorithm.</p>
<p>This process is repeated for every pixel in the image, just like a regular convolution process. And each time, we consider increasing distances between pixels for computation of final values at increasing scales. </p>
<p>Let's look at just one more scale.</p>
<p><strong>Scale 2</strong>: This is where things get even more interesting. At scale 2 the value of 2<sup>n</sup> becomes <strong>4</strong>. This means that for convolution, we'll jump directly to pixels that are <strong>4</strong> locations apart from the target pixel:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/scale2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>8x8px grid with pixels that are involved in convolution for pixel number 28 highlighted at scale 2</em></p>
<p>Wait what? Why are we choosing pixels 1, 4, 8, 25, &amp; 57? 1 &amp; 4 are only 3 locations apart, 25 is only 2 locations apart, and 8 &amp; 57 are not even diagonally aligned with the target pixel. What's going on?</p>
<h3 id="heading-handling-boundary-conditions">Handling Boundary Conditions</h3>
<p>As we've mentioned that this process is executed for all of the pixels in an image, we also need to consider cases where the pixel locations for convolution lie outside of the image.</p>
<p>This is not a concept unique to this algorithm. During convolution, this is referred to as a boundary condition or handling boundary pixels. There are various techniques for dealing with this, and all of them involve virtually extending the image in order to make it seem like we're not encountering the boundary at all.</p>
<p>Some of the techniques are:</p>
<ul>
<li>Extending as much as needed by copying the value of the last row/column</li>
<li>Mirroring the image on all edges and corners</li>
<li>Wrapping the image around the edges.</li>
</ul>
<p>In our example, we're employing the "mirroring" technique. When implementing such an algorithm, we don't need to actually create an extended image. Any boundary handling is implementable using just basic mathematical formulae.</p>
<p>Our extended image, with the correct pixels selected for scale 2, is as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/scale2-mirrored.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source image extended on all edges and corners using the mirroring technique. All of the faded regions represent extended areas.</em></p>
<p>Again, the extension is only logical and is completely computed using formulae, as opposed to actually extending the source image and then checking. We can easily see that with the mirrored images in place, our basic rule of picking pixels that are 2<sup>n</sup> locations apart is still followed.</p>
<h3 id="heading-computing-maximum-possible-scales-for-any-given-image">Computing Maximum Possible Scales for Any Given Image</h3>
<p>If you think about it carefully, you'll see that the maximum layers an image can be decomposed into can be calculated by computing the log<sub>2</sub> of the image width or height (whichever is lower) and throwing away the fractional part. </p>
<p>In our 5x5 image, log<sub>2</sub>(5) ~= <strong>2.32</strong>. If we throw away the fractional part, that leaves us with 2 layers. Similarly, for a 1000x1000px image, log<sub>2</sub>1000 ~= <strong>9.96</strong>, which means we can decompose a 1000x1000 px image into a maximum of 9 layers. It simply implies that our "holes" cannot be larger than the width or height.</p>
<p>Even with the mirroring extension we used above, if the holes are larger than the width of the image, they'll still end up outside of the extended regions, specially for corner or boundary pixels, making it impossible to perform convolution at that scale.</p>
<h3 id="heading-closing-notes">Closing Notes</h3>
<p>Thinking about the examples and visualisations a bit more, you can clearly see how and why this algorithm works, and how it's able to separate out structures in an image based on their sizes. The increasing hole sizes make it so that only structures larger than the hole itself are retained for any given layer.</p>
<p>A big advantage of using this algorithm is the computational cost. Since this doesn't involve Fourier or Wavelet transforms, the computational cost is quite low, relatively speaking. The memory cost, however, is indeed higher. But more often than not that is a good tradeoff.</p>
<p>Another advantage of this algorithm when comparing it to other discreet wavelet transform algorithms is that the size of source image is preserved throughout the entire process. There's no decimation or upscaling happening here, making this algorithm one of the easiest ones to understand and implement.</p>
<p>The algorithm is used in almost all of the astronomical image processing softwares such as <a target="_blank" href="https://pixinsight.com/">PixInsight</a>, <a target="_blank" href="https://siril.org/">Siril</a>, and many others.</p>
<p>This algorithm is also known by other names such as <strong>Stationary Wavelet Transform</strong> and <strong>Starlet Transform</strong>.</p>
<h2 id="heading-part-2-how-to-implement-a-trous-tranform-in-rust">Part 2: How to Implement <em>À Trous</em> Tranform in Rust</h2>
<p>Now I'm going to show you how you can implement this algorithm in Rust. </p>
<p>For the purposes of this tutorial, I'm going to assume that you're pretty familiar with Rust and its basic concepts, such as data-types, iterators, and traits and are comfortable writing programs that use these concepts. </p>
<p>I'm also going to assume that you have an understanding of what convolution and convolution kernels mean in this context.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>We're going to need a couple of dependencies. Before we get to that, let's quickly create a new project:</p>
<pre><code class="lang-shell">cargo new --lib atrous-rs
cd atrous-rs
</code></pre>
<p>Now let's all of the dependencies we need. We actually only need 2:</p>
<pre><code class="lang-shell">cargo add image ndarray
</code></pre>
<p><strong><code>image</code></strong> is a Rust library we'll use to work with images of all of the standard formats and encodings. It also helps us convert between various formats, and provides easy access to pixel data as buffers.</p>
<p><strong><code>ndarray</code></strong> is a Rust library that helps you you create, manipulate, and work with 2D, 3D, or N-Dimensional arrays. We can use nested Vectors, but using a project like ndarray is better in this case because we need to perform a lot of operations on both individual values as well as their neighbours. Not only is it much easier to do with <strong>ndarray</strong>, but they also have performance optimisations built in for many operations and CPU types.</p>
<p>Although I'll be covering the basic functions/traits/methods/data-types we use from these crates, I'm not going to go into too much detail for them. I encourage you to read the docs instead.</p>
<p>We're actually going to jump straight to algorithm implementation, and come back later to see how we can use it.</p>
<h3 id="heading-the-a-trous-transform">The <em>À Trous</em> Transform</h3>
<p>Create a new file that will hold our implementation. Let's name it <code>transform.rs</code>.</p>
<p>Start with adding the following struct, that will hold the information we need to perform the transform:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// transform.rs</span>

<span class="hljs-keyword">use</span> ndarray::Array2;

<span class="hljs-keyword">pub</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">ATrousTransform</span></span> {
    input: Array2&lt;<span class="hljs-built_in">f32</span>&gt;, <span class="hljs-comment">// `Array2&lt;f32&gt;` is a 2D array where each value is of type `f32`. This will hold our pixel data for input image.</span>
    levels: <span class="hljs-built_in">usize</span>, <span class="hljs-comment">// The number of levels or scales to decompose the image into</span>
    current_level: <span class="hljs-built_in">usize</span>, <span class="hljs-comment">// Current level that we need to generate. This holds the state of our iterator.</span>
    width: <span class="hljs-built_in">usize</span>, <span class="hljs-comment">// Width of input image</span>
    height: <span class="hljs-built_in">usize</span>, <span class="hljs-comment">// Height of input image</span>
}
</code></pre>
<p>We also need a way to create this struct easily. In our case, we want to be able to create it from the input image directly. Also, input image can be of any of the supported format and encoding, but we want a consistent color-type to implement the calculations, so we'll also need to convert the image to our expected format.</p>
<p>It's helpful to extract all of this logic away using the "constructor" pattern in Rust. Let's implement that:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// transform.rs</span>

<span class="hljs-keyword">use</span> image::GenericImageView;

<span class="hljs-keyword">impl</span> ATrousTransform {
    <span class="hljs-keyword">pub</span> <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">new</span></span>(input: &amp;image::DynamicImage, levels: <span class="hljs-built_in">usize</span>) -&gt; <span class="hljs-keyword">Self</span> {
        <span class="hljs-keyword">let</span> (width, height) = input.dimensions();
        <span class="hljs-keyword">let</span> (width, height) = (width <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>, height <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>);

        <span class="hljs-comment">// Create a new 2D array with proper size for each dimension to hold all of our input's pixel data. Method `zeros` takes a "shape" parameter, which is a tuple of (rows_count, columns_count).</span>
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> data = Array2::&lt;<span class="hljs-built_in">f32</span>&gt;::zeros((height, width));

        <span class="hljs-comment">// Convert the image to be a grayscale image where each pixel value is of type `f32`. Loop over all pixels in the input image along with its 2D location.</span>
        <span class="hljs-keyword">for</span> (x, y, pixel) <span class="hljs-keyword">in</span> input.to_luma32f().enumerate_pixels() {
            <span class="hljs-comment">// Put the pixel value at appropriate location in our data array. The `[[]]` syntax is used to provide a 2-dimensional index such as `[[row_index, col_index]]`</span>
            data[[y <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>, x <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>]] = pixel.<span class="hljs-number">0</span>[<span class="hljs-number">0</span>];
        }

        <span class="hljs-keyword">Self</span> {
            input: data,
            levels,
            current_level: <span class="hljs-number">0</span>,
            width,
            height
        }
    }
}
</code></pre>
<p>This takes care of converting the image to grayscale and converting the pixel values to <code>f32</code>. If you're not already aware, for images with floating-point pixel values, the values are always normalized. This means that they are always between 0 and 1 – 0 representing black and 1 representing white.</p>
<h3 id="heading-iterators-and-the-a-trous-transform">Iterators and the <em>À Trous</em> Transform</h3>
<p>Before we continue, let's think about the algorithm for a second. We need to be able to generate images at increasing scales, until we hit the maximum number of levels we need. </p>
<p>We want the consumer of our library to have access to all of these scales, and be able to manipulate them and also easily recombine once they're done. They need to be able to filter layers to ignore structures at certain scales, manipulate or "map" them to change their characteristics, perform operations on them, or even store each image if they so need.</p>
<p>This sounds an awful lot like Iterators! Iterators give us methods like <code>filter</code>, <code>skip</code>, <code>take</code>, <code>map</code>, <code>for_each</code>, and so on, all of which are exactly all we need to work with our layers before recomposition.</p>
<p>One added advantage of Iterators is that it allows you to finish processing each layer all the way through before you move on to the next one. If you're unsure why this is, I suggest reading more about <a target="_blank" href="https://doc.rust-lang.org/book/ch13-02-iterators.html">processing a series of items with Iterators in Rust</a>.</p>
<p>We're going implement the <code>Iterator</code> trait for our <code>ATrousTransform</code> type which should produce a wavelet layer as output for each iteration. </p>
<p>We're going to be implementing the inner-most parts of the algorithm first, and build out from there. So we first need a way to convolve an input data buffer with the scaling function while making sure that adjacent pixels are 2<sup>n</sup> locations apart, which is the first step in our loop.</p>
<h3 id="heading-convolution">Convolution</h3>
<p>We need to define our convolution kernel before we can do anything else. Create a new file <code>kernel.rs</code> and add it to <code>lib.rs</code> with the following contents:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// kernel.rs</span>

<span class="hljs-meta">#[derive(Copy, Clone)]</span>
<span class="hljs-keyword">pub</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">LinearInterpolationKernel</span></span> {
    values: [[<span class="hljs-built_in">f32</span>; <span class="hljs-number">3</span>]; <span class="hljs-number">3</span>]
}

<span class="hljs-keyword">impl</span> <span class="hljs-built_in">Default</span> <span class="hljs-keyword">for</span> LinearInterpolationKernel {
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">default</span></span>() -&gt; <span class="hljs-keyword">Self</span> {
        <span class="hljs-keyword">Self</span> {
            values: [
                [<span class="hljs-number">1</span>. / <span class="hljs-number">16</span>., <span class="hljs-number">1</span>. / <span class="hljs-number">8</span>., <span class="hljs-number">1</span>. / <span class="hljs-number">16</span>.],
                [<span class="hljs-number">1</span>. / <span class="hljs-number">8</span>., <span class="hljs-number">1</span>. / <span class="hljs-number">4</span>., <span class="hljs-number">1</span>. / <span class="hljs-number">8</span>.],
                [<span class="hljs-number">1</span>. / <span class="hljs-number">16</span>., <span class="hljs-number">1</span>. / <span class="hljs-number">8</span>., <span class="hljs-number">1</span>. / <span class="hljs-number">16</span>.],
            ]
        }
    }
}
</code></pre>
<p>We define it using a struct instead of a constant array of arrays because we need to define some tiny helpful methods on it related to index handling. We'll come back to that later.</p>
<p>Create another file <code>convolve.rs</code>. This is where all of the code for handling convolution for individual pixels will go. We'll define a <code>Convolution</code> trait that will define methods needed to perform the convolution on every pixel in current layer.</p>
<pre><code class="lang-rust"><span class="hljs-comment">// convolve.rs</span>

<span class="hljs-keyword">pub</span> <span class="hljs-class"><span class="hljs-keyword">trait</span> <span class="hljs-title">Convolution</span></span> {
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">compute_pixel_index</span></span>(
        &amp;<span class="hljs-keyword">self</span>,
        distance: <span class="hljs-built_in">usize</span>,
        kernel_index: [<span class="hljs-built_in">isize</span>; <span class="hljs-number">2</span>],
        target_pixel_index: [<span class="hljs-built_in">usize</span>; <span class="hljs-number">2</span>]
    ) -&gt; [<span class="hljs-built_in">usize</span>; <span class="hljs-number">2</span>];

    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">compute_convoluted_pixel</span></span>(
        &amp;<span class="hljs-keyword">self</span>, 
        distance: <span class="hljs-built_in">usize</span>, 
        index: [<span class="hljs-built_in">usize</span>; <span class="hljs-number">2</span>]
    ) -&gt; <span class="hljs-built_in">f32</span>;
}
</code></pre>
<p>You may ask why we need a trait here instead of a simple <code>impl</code> block. We are only working with Grayscale images in this article, but you may want to extend it to implement it for RGB or other color modes as well.</p>
<p>Now, you need to implement this trait for your <code>ATrousTransform</code> struct:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// convolve.rs</span>

<span class="hljs-keyword">impl</span> Convolution <span class="hljs-keyword">for</span> ATrousTransform {
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">compute_pixel_index</span></span>(
        &amp;<span class="hljs-keyword">self</span>, 
        distance: <span class="hljs-built_in">usize</span>, 
        kernel_index: [<span class="hljs-built_in">isize</span>; <span class="hljs-number">2</span>], 
        target_pixel_index: [<span class="hljs-built_in">usize</span>; <span class="hljs-number">2</span>]
    ) -&gt; [<span class="hljs-built_in">usize</span>; <span class="hljs-number">2</span>] {
        <span class="hljs-keyword">let</span> [kernel_index_x, kernel_index_y] = kernel_index;

        <span class="hljs-comment">// Compute the actual distance of adjacent pixel</span>
        <span class="hljs-comment">// by multiplying their relative position with the</span>
        <span class="hljs-comment">// size of the hole.</span>
        <span class="hljs-keyword">let</span> x_distance = kernel_index_x * distance <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span>;
        <span class="hljs-keyword">let</span> y_distance = kernel_index_y * distance <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span>;

        <span class="hljs-keyword">let</span> [x, y] = target_pixel_index;

        <span class="hljs-comment">// Compute the index of adjacent pixel in the 2D</span>
        <span class="hljs-comment">// image based on the index of current pixel.</span>
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> x = x <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span> + x_distance;
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> y = y <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span> + y_distance;

        <span class="hljs-comment">// If x index is out of bounds, consider x to be</span>
        <span class="hljs-comment">// the nearest boundary location</span>
        <span class="hljs-keyword">if</span> x &lt; <span class="hljs-number">0</span> {
            x = <span class="hljs-number">0</span>;
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> x &gt; <span class="hljs-keyword">self</span>.width <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span> - <span class="hljs-number">1</span> {
            x = <span class="hljs-keyword">self</span>.width <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span> - <span class="hljs-number">1</span>;
        }

        <span class="hljs-comment">// If y index is out of bounds, consider y to be</span>
        <span class="hljs-comment">// the nearest boundary location</span>
        <span class="hljs-keyword">if</span> y &lt; <span class="hljs-number">0</span> {
            y = <span class="hljs-number">0</span>;
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> y &gt; <span class="hljs-keyword">self</span>.height <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span> - <span class="hljs-number">1</span> {
            y = <span class="hljs-keyword">self</span>.height <span class="hljs-keyword">as</span> <span class="hljs-built_in">isize</span> - <span class="hljs-number">1</span>;
        }

        <span class="hljs-comment">// The final 2D index of pixel.</span>
        [y <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>, x <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>]
    }

    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">compute_convoluted_pixel</span></span>(
        &amp;<span class="hljs-keyword">self</span>, 
        distance: <span class="hljs-built_in">usize</span>, 
        [x, y]: [<span class="hljs-built_in">usize</span>; <span class="hljs-number">2</span>]
    ) -&gt; <span class="hljs-built_in">f32</span> {
        <span class="hljs-comment">// Create new variable to hold the result of convolution</span>
        <span class="hljs-comment">// for current pixel.</span>
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> pixels_sum = <span class="hljs-number">0.0</span>;

        <span class="hljs-keyword">let</span> kernel = LinearInterpolationKernel::default();

        <span class="hljs-comment">// Iterate over relative position of pixels from the center</span>
        <span class="hljs-comment">// pixel to perform convolution with. In other words, </span>
        <span class="hljs-comment">// these are the indexes of neighbouring pixels from the</span>
        <span class="hljs-comment">// center pixel.</span>
        <span class="hljs-keyword">for</span> kernel_index_x <span class="hljs-keyword">in</span> -<span class="hljs-number">1</span>..=<span class="hljs-number">1</span> {
            <span class="hljs-keyword">for</span> kernel_index_y <span class="hljs-keyword">in</span> -<span class="hljs-number">1</span>..=<span class="hljs-number">1</span> {
                <span class="hljs-comment">// Get the computed pixel location that maps to</span>
                <span class="hljs-comment">// the current position in kernel</span>
                <span class="hljs-keyword">let</span> pixel_index = <span class="hljs-keyword">self</span>.compute_pixel_index(
                    distance,
                    [kernel_index_x, kernel_index_y],
                    [x, y]
                );

                <span class="hljs-comment">// Get the multiplicative factor (kernel value) for </span>
                <span class="hljs-comment">// this relative location from the kernel.</span>
                <span class="hljs-keyword">let</span> kernel_value = kernel.value_from_relative_index(
                    kernel_index_x,
                    kernel_index_y
                );

                <span class="hljs-comment">// Multiply the pixel value with kernel scaling</span>
                <span class="hljs-comment">// factor and add it to the pixel sum.</span>
                pixels_sum += kernel_value * <span class="hljs-keyword">self</span>.input[pixel_index];
            }
        }

        <span class="hljs-comment">// Return the value of computed pixel from convolution process.</span>
        pixels_sum
    }
}
</code></pre>
<p>We need to do computations to figure out each pixel's location based on the relative position in the kernel from the center pixel as well as ensure that the "hole size" is also being taken into consideration for the final pixel index. As you might notice, you also want to handle the boundary conditions when computing indexes.</p>
<p>I encourage to take your time here and go through the code and the comments.</p>
<h3 id="heading-implementing-the-iterator">Implementing the Iterator</h3>
<p>It's finally time to implement the <code>Iterator</code> trait for your <code>ATrousTransform</code>:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// transform.rs</span>

<span class="hljs-keyword">impl</span> <span class="hljs-built_in">Iterator</span> <span class="hljs-keyword">for</span> ATrousTransform {
    <span class="hljs-comment">// Our output is an image as well as the current level for each</span>
    <span class="hljs-comment">// iteration. The current level is an `Option` to represent the</span>
    <span class="hljs-comment">// final residue layer after the intermediary layers have been</span>
    <span class="hljs-comment">// generated.</span>
    <span class="hljs-class"><span class="hljs-keyword">type</span> <span class="hljs-title">Item</span></span> = (Array2::&lt;<span class="hljs-built_in">f32</span>&gt;, <span class="hljs-built_in">Option</span>&lt;<span class="hljs-built_in">usize</span>&gt;);

    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">next</span></span>(&amp;<span class="hljs-keyword">mut</span> <span class="hljs-keyword">self</span>) -&gt; <span class="hljs-built_in">Option</span>&lt;Self::Item&gt; {
        <span class="hljs-keyword">let</span> pixel_scale = <span class="hljs-keyword">self</span>.current_level;
        <span class="hljs-keyword">self</span>.current_level += <span class="hljs-number">1</span>;

        <span class="hljs-comment">// We've already generated all the layers. Return None to </span>
        <span class="hljs-comment">// exit the iterator.</span>
        <span class="hljs-keyword">if</span> pixel_scale &gt; <span class="hljs-keyword">self</span>.levels {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>;
        }

        <span class="hljs-comment">// We've generated all intermediary layers, return the </span>
        <span class="hljs-comment">// residue layer.</span>
        <span class="hljs-keyword">if</span> pixel_scale == <span class="hljs-keyword">self</span>.levels {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">Some</span>((<span class="hljs-keyword">self</span>.input.clone(), <span class="hljs-literal">None</span>))
        }

        <span class="hljs-keyword">let</span> (width, height) = (<span class="hljs-keyword">self</span>.width, <span class="hljs-keyword">self</span>.height);

        <span class="hljs-comment">// Distance between adjacent pixels for convolution (also </span>
        <span class="hljs-comment">// referred to as size of "hole").</span>
        <span class="hljs-keyword">let</span> distance = <span class="hljs-number">2_usize</span>.pow(pixel_scale <span class="hljs-keyword">as</span> <span class="hljs-built_in">u32</span>);

        <span class="hljs-comment">// Create new buffer to hold the computed data for this layer.</span>
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> current_data = Array2::&lt;<span class="hljs-built_in">f32</span>&gt;::zeros((height, width));

        <span class="hljs-comment">// Iterate over each pixel location in the 2D image</span>
        <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>..width {
            <span class="hljs-keyword">for</span> y <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>..height {
                <span class="hljs-comment">// Set the current pixel in current layer to</span>
                <span class="hljs-comment">// the result of convolution on the current</span>
                <span class="hljs-comment">// pixel in input data.</span>
                current_data[[y, x]] = <span class="hljs-keyword">self</span>.compute_convoluted_pixel(
                    distance, 
                    [x, y]
                );
            }
        }

        <span class="hljs-comment">// Create current layer by subtracting currently computed pixels </span>
        <span class="hljs-comment">// from previous layer</span>
        <span class="hljs-keyword">let</span> final_data = <span class="hljs-keyword">self</span>.input.clone() - &amp;current_data;

        <span class="hljs-comment">// Set the input layer to equal the current computed layer so </span>
        <span class="hljs-comment">// that it can be used as the "previous layer" in next iteration.</span>
        <span class="hljs-comment">// This is also our residue data for each layer.</span>
        <span class="hljs-keyword">self</span>.input = current_data;

        <span class="hljs-comment">// Return the current layer data as well as current level information.</span>
        <span class="hljs-literal">Some</span>((final_data, <span class="hljs-literal">Some</span>(<span class="hljs-keyword">self</span>.current_level)))
    }
}
</code></pre>
<p>I'm going to point out that there's a lot of potential for optimizing for performance here, but that's out of the scope of this article.</p>
<p>We'll finally look at how we can take all of these layers and reconstruct our input image.</p>
<h3 id="heading-recomposition">Recomposition</h3>
<p>As I've said previously, reconstructing an image that was decomposed with the A Trous transform is as simple as summing all of the layers together.</p>
<p>We're going to define a trait for this. Why we need a trait here should be clear once you look at the implementation.</p>
<p>Create a new file <code>recompose.rs</code> with the following contents:</p>
<pre><code class="lang-rust"><span class="hljs-comment">// recompose.rs</span>

<span class="hljs-keyword">use</span> image::{DynamicImage, ImageBuffer, Luma};
<span class="hljs-keyword">use</span> ndarray::Array2;

<span class="hljs-keyword">pub</span> <span class="hljs-class"><span class="hljs-keyword">trait</span> <span class="hljs-title">RecomposableLayers</span></span>: <span class="hljs-built_in">Iterator</span>&lt;Item = (Array2&lt;<span class="hljs-built_in">f32</span>&gt;, <span class="hljs-built_in">Option</span>&lt;<span class="hljs-built_in">usize</span>&gt;)&gt; {
    <span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">recompose_into_image</span></span>(
        <span class="hljs-keyword">self</span>,
        width: <span class="hljs-built_in">usize</span>,
        height: <span class="hljs-built_in">usize</span>,
    ) -&gt; DynamicImage
        <span class="hljs-keyword">where</span>
            <span class="hljs-keyword">Self</span>: <span class="hljs-built_in">Sized</span>,
    {
        <span class="hljs-comment">// Create a result buffer to hold the pixel data for our output image.</span>
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> result = Array2::&lt;<span class="hljs-built_in">f32</span>&gt;::zeros((height, width));

        <span class="hljs-comment">// For each layer, add the layer data to current value of result buffer.</span>
        <span class="hljs-keyword">for</span> layer <span class="hljs-keyword">in</span> <span class="hljs-keyword">self</span> {
            result += &amp;layer.<span class="hljs-number">0</span>;
        }

        <span class="hljs-comment">// Compute min and max pixel intensity values in the final data so that</span>
        <span class="hljs-comment">// we can perform a "rescale", which normalizes all pixel values to be</span>
        <span class="hljs-comment">// between the range of 0 &amp; 1, as is expected by float 32 images.</span>
        <span class="hljs-keyword">let</span> min_pixel = result.iter().copied().reduce(<span class="hljs-built_in">f32</span>::min).unwrap();
        <span class="hljs-keyword">let</span> max_pixel = result.iter().copied().reduce(<span class="hljs-built_in">f32</span>::max).unwrap();

        <span class="hljs-comment">// Create a new `ImageBuffer`, which is a type provided by `image` crate to</span>
        <span class="hljs-comment">// serve as buffer for pixel data of an image. Here, we're creating a new</span>
        <span class="hljs-comment">// `Luma` ImageBuffer with pixel value of type `u16`. Luma just refers to</span>
        <span class="hljs-comment">// grayscale.</span>
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> result_img: ImageBuffer&lt;Luma&lt;<span class="hljs-built_in">u16</span>&gt;, <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">u16</span>&gt;&gt; =
            ImageBuffer::new(width <span class="hljs-keyword">as</span> <span class="hljs-built_in">u32</span>, height <span class="hljs-keyword">as</span> <span class="hljs-built_in">u32</span>);

        <span class="hljs-comment">// Pre-compute the denominator for scaling computation so that we don't</span>
        <span class="hljs-comment">// repeat this unnecessarily for every iteration.</span>
        <span class="hljs-keyword">let</span> rescale_ratio = max_pixel - min_pixel;

        <span class="hljs-comment">// Iterate over all pixels in the `ImageBuffer` and fill it based on data</span>
        <span class="hljs-comment">// from the `result` buffer after rescaling the value.</span>
        <span class="hljs-keyword">for</span> (x, y, pixel) <span class="hljs-keyword">in</span> result_img.enumerate_pixels_mut() {
            <span class="hljs-keyword">let</span> intensity = result[(y <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>, x <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>)];

            *pixel =
                Luma([((intensity - min_pixel) / rescale_ratio * <span class="hljs-built_in">u16</span>::MAX <span class="hljs-keyword">as</span> <span class="hljs-built_in">f32</span>) <span class="hljs-keyword">as</span> <span class="hljs-built_in">u16</span>]);
        }

        <span class="hljs-comment">// Convert the `ImageBuffer` into `DynamicImage` and return it</span>
        DynamicImage::ImageLuma16(result_img)
    }
}

<span class="hljs-comment">// Implement this trait for anything that implements the Iterator trait</span>
<span class="hljs-comment">// with the given item type</span>
<span class="hljs-keyword">impl</span>&lt;T&gt; RecomposableLayers <span class="hljs-keyword">for</span> T <span class="hljs-keyword">where</span> T: <span class="hljs-built_in">Iterator</span>&lt;Item = (Array2&lt;<span class="hljs-built_in">f32</span>&gt;, <span class="hljs-built_in">Option</span>&lt;<span class="hljs-built_in">usize</span>&gt;)&gt; {}
</code></pre>
<p>If you haven't noticed, since we implement this trait for a generic, this will work with any iterator, such as <code>Filter</code>, <code>Map</code>, and so on. If you didn't use a trait here, you'll have had to implement the same thing again and again for every built-in iterator type, and your code wouldn't have worked with 3rd party types.</p>
<h3 id="heading-using-the-a-trous-transform">Using the <em>À Trous</em> Transform</h3>
<p>After all of that, it's finally time to reproduce the processing that I showed you for the galaxy image with lots of noise. Create a new file <code>main.rs</code> with the following contents:</p>
<pre><code class="lang-rust"><span class="hljs-keyword">use</span> image::{DynamicImage, ImageBuffer, Luma};
<span class="hljs-keyword">use</span> atrous::recompose::RecomposableLayers;
<span class="hljs-keyword">use</span> atrous::transform::ATrousTransform;

<span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-comment">// Open our noisy image</span>
    <span class="hljs-keyword">let</span> image = image::open(<span class="hljs-string">"m33-noise-lum.jpg"</span>).unwrap();

    <span class="hljs-comment">// Create a new instance of the transform with 9 layers</span>
    <span class="hljs-keyword">let</span> transform = ATrousTransform::new(&amp;image, <span class="hljs-number">9</span>);

    <span class="hljs-comment">// Map over each layer</span>
    transform.map(|(<span class="hljs-keyword">mut</span> buffer, pixel_scale)| {
        <span class="hljs-comment">// Create a new image buffer to hold the pixel data. This</span>
        <span class="hljs-comment">// will be populated from the raw buffer for this layer.</span>
        <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> new_buffer =
            ImageBuffer::&lt;Luma&lt;<span class="hljs-built_in">u16</span>&gt;, <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">u16</span>&gt;&gt;::new(buffer.ncols() <span class="hljs-keyword">as</span> <span class="hljs-built_in">u32</span>, buffer.nrows() <span class="hljs-keyword">as</span> <span class="hljs-built_in">u32</span>);

        <span class="hljs-comment">// Iterate over all pixels of the `ImageBuffer` to populate it. We also</span>
        <span class="hljs-comment">// convert from `f32` pixels to `u16` pixels.</span>
        <span class="hljs-keyword">for</span> (x, y, pixel) <span class="hljs-keyword">in</span> new_buffer.enumerate_pixels_mut() {
            *pixel = Luma([(buffer[[y <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>, x <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>]] * <span class="hljs-built_in">u16</span>::MAX <span class="hljs-keyword">as</span> <span class="hljs-built_in">f32</span>) <span class="hljs-keyword">as</span> <span class="hljs-built_in">u16</span>])
        }

        <span class="hljs-comment">// If the present layer is a small scale layer (&lt; 3), </span>
        <span class="hljs-comment">// perform noise reduction</span>
        <span class="hljs-keyword">if</span> pixel_scale.is_some_and(|scale| scale &lt; <span class="hljs-number">3</span>) {
            <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> image = DynamicImage::ImageLuma16(new_buffer).to_luma8();

            <span class="hljs-comment">// Bilateral filter is a de-noising filter. Apply it to the image.</span>
            image = imageproc::filter::bilateral_filter(&amp;image, <span class="hljs-number">10</span>, <span class="hljs-number">10</span>., <span class="hljs-number">3</span>.);

            <span class="hljs-comment">// Modify the raw buffer to contain the updated pixel values after</span>
            <span class="hljs-comment">// filtering.</span>
            <span class="hljs-keyword">for</span> (x, y, pixel) <span class="hljs-keyword">in</span> image.enumerate_pixels() {
                buffer[[y <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>, x <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>]] = pixel.<span class="hljs-number">0</span>[<span class="hljs-number">0</span>] <span class="hljs-keyword">as</span> <span class="hljs-built_in">f32</span> / <span class="hljs-built_in">u8</span>::MAX <span class="hljs-keyword">as</span> <span class="hljs-built_in">f32</span>;
            }

            <span class="hljs-comment">// Return the updated buffer.</span>
            (buffer, pixel_scale)
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Return the unmodified buffer for larger scale layers.</span>
            (buffer, pixel_scale)
        }
    })
        <span class="hljs-comment">// Call the recomposition method on iterator</span>
        .recompose_into_image(image.width() <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>, image.height() <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span>)
        <span class="hljs-comment">// Convert output to 8-bit grayscale image</span>
        .to_luma8()
        <span class="hljs-comment">// Save it to jpg file</span>
        .save(<span class="hljs-string">"noise-reduced.jpg"</span>)
        .unwrap()
}
</code></pre>
<p>You also need to add a new dependency, <code>imageproc</code>, which provides useful image processing implementations on top of the <code>image</code> crate.</p>
<pre><code class="lang-shell">cargo add imageproc
</code></pre>
<p>To make this work, we also need to modify our <code>Cargo.toml</code> to explicitly define both binary and library targets:</p>
<pre><code class="lang-toml">// Cargo.toml

<span class="hljs-section">[package]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"atrous-rs"</span>
<span class="hljs-attr">version</span> = <span class="hljs-string">"0.1.0"</span>
<span class="hljs-attr">edition</span> = <span class="hljs-string">"2021"</span>

<span class="hljs-section">[[bin]]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"atrous"</span>
<span class="hljs-attr">path</span> = <span class="hljs-string">"src/main.rs"</span>

<span class="hljs-section">[lib]</span>
<span class="hljs-attr">name</span> = <span class="hljs-string">"atrous"</span>
<span class="hljs-attr">path</span> = <span class="hljs-string">"src/lib.rs"</span>

<span class="hljs-comment"># See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html</span>

<span class="hljs-section">[dependencies]</span>
<span class="hljs-attr">image</span> = <span class="hljs-string">"0.25.1"</span>
<span class="hljs-attr">imageproc</span> = <span class="hljs-string">"0.24.0"</span>
<span class="hljs-attr">ndarray</span> = <span class="hljs-string">"0.15.6"</span>
</code></pre>
<p>You may download the test image from <a target="_blank" href="https://anshulsanghi-assets.s3.ap-south-1.amazonaws.com/m33-noise-lum.jpg">here</a>. Move it to the root directory of your project, and run <code>cargo run --release</code>. Once it finishes, you should have a new file <code>noise-reduced.jpg</code> as the output of our process.</p>
<p>And there we have it.</p>
<h2 id="heading-further-reading">Further Reading</h2>
<p>These are some of the resources that were very helpful to me when I was learning about this algorithm and how to use it. I highly encourage anyone who wants a more technical understanding of the algorithm to check these out.</p>
<ul>
<li><a target="_blank" href="https://www.eso.org/sci/software/esomidas/doc/user/18NOV/volb/node317.html">The <em>à trous</em> algorithm</a> </li>
<li><a target="_blank" href="https://www.pixinsight.com/doc/legacy/LE/20_wavelets/a_trous_wavelet_transform/a_trous_wavelet_transform.html">The <em>À Trous</em> Discrete Wavelet Transform In PixInsight</a></li>
<li><a target="_blank" href="https://jstarck.cosmostat.org/publications/books/book2/">Astronomical Image and Data Analysis</a> by Jean-Luc Starck and Fionn Murtagh</li>
<li><a target="_blank" href="https://jstarck.cosmostat.org/publications/books/book-2015/">Sparse Image and Signal Processing: Wavelets and Related Geometric Multiscale Analysis</a> by J.L. Starck, F. Murtagh, and J. Fadili</li>
</ul>
<p>In addition, I've created a Rust library for working with <em>À Trous</em> transform. It closely matches with what I've showed you here, but has some additional features already, and will have even more. </p>
<p>Things such as handling RGB images and working with all the 3 different kernels is already implemented. It also has better logic for handling boundary conditions, where it uses the image folding technique.</p>
<p>I'm also soon going to be working on performance improvements for the same.</p>
<p>If you want to learn more, or contribute to the library, feel free to do so. The repository can be found here: <a target="_blank" href="https://github.com/anshap1719/image-dwt">https://github.com/anshap1719/image-dwt</a>  </p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>I hope you enjoyed the journey so far. If image processing techniques or their implementation in Rust is something that interests you, then stay tuned for more as these are the topics I love writing about.</p>
<p>Also, feel free to <a target="_blank" href="mailto:nitric-brisk.0s@icloud.com"><strong>contact me</strong></a> if you have any questions or opinions on this topic.</p>
<h3 id="heading-enjoying-my-work">Enjoying my work?</h3>
<p>Consider buying me a coffee to support my work!</p>


<p>Till next time, happy coding and wishing you clear skies!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Top 10 JavaScript Algorithms for Coding Challenges ]]>
                </title>
                <description>
                    <![CDATA[ Are you gearing up for coding interviews and looking to strengthen your grasp on JavaScript algorithms? We just posted a course on the freeCodeCamp Community YouTube channel that will equip you with the essential skills to excel in Leetcode-style cod... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/top-10-javascript-algorithms-for-coding-challenges/</link>
                <guid isPermaLink="false">66b206aaeea9870582e16cd6</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 12 Mar 2024 17:37:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/jsalgs.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you gearing up for coding interviews and looking to strengthen your grasp on JavaScript algorithms?</p>
<p>We just posted a course on the freeCodeCamp Community YouTube channel that will equip you with the essential skills to excel in Leetcode-style coding challenges. Mukhtar from Coding Monkey developed this course.</p>
<p>The course begins with an introduction that sets the stage for what you're about to learn. It emphasizes the significance of algorithms in coding interviews and how mastering them can be a game-changer for your career. The course is structured to transform your approach to problem-solving, enabling you to tackle Leetcode problems with newfound confidence.</p>
<p>Here are some of the algorithms and challenges you will learn about:</p>
<h3 id="heading-reverse-string-amp-integers">Reverse String &amp; Integers</h3>
<p>Learn how to manipulate strings and integers by reversing them. This section teaches the fundamental techniques for reversing data types, a common task in coding interviews that tests your understanding of strings and number manipulation.</p>
<h3 id="heading-palindrome">Palindrome</h3>
<p>A palindrome is a word, phrase, number, or other sequences of characters that reads the same forward and backward. This section covers the strategies to determine whether a given input is a palindrome, showcasing your ability to work with strings and logic.</p>
<h3 id="heading-max-char">Max Char</h3>
<p>Identify the most frequently occurring character in a string. This algorithm is crucial for understanding character mapping and frequency analysis, which are pivotal in many coding challenges.</p>
<h3 id="heading-array-chunking">Array Chunking</h3>
<p>Learn to divide an array into chunks of a specified size, a vital skill for data manipulation and organization in coding tasks.</p>
<h3 id="heading-title-case">Title Case</h3>
<p>Transform the casing of strings to title case, where the first letter of each word is capitalized. This section hones your string manipulation skills and attention to detail.</p>
<h3 id="heading-anagrams">Anagrams</h3>
<p>Discover how to check if two strings are anagrams of each other, meaning they contain the same characters in a different order. This algorithm tests your ability to analyze and rearrange data.</p>
<h3 id="heading-count-vowels">Count Vowels</h3>
<p>Counting vowels in a string is a fundamental task that reinforces your understanding of string traversal and character comparison.</p>
<h3 id="heading-fizz-buzz">Fizz Buzz</h3>
<p>A classic problem that combines numbers and strings. You'll learn to output "Fizz," "Buzz," or "FizzBuzz" based on a number's divisibility, sharpening your logical thinking and control flow mastery.</p>
<h3 id="heading-steps-string-pattern">Steps String Pattern</h3>
<p>Create a step-like pattern using strings, a unique challenge that enhances your understanding of nested loops and string manipulation.</p>
<h3 id="heading-pyramid-string-pattern">Pyramid String Pattern</h3>
<p>Build a pyramid with strings. This algorithm takes your loop skills further, challenging you to create a visually structured output.</p>
<h3 id="heading-spiral-matrix">Spiral Matrix</h3>
<p>As a bonus, the course offers a section on creating a spiral matrix, an advanced challenge that will test your array manipulation and pattern recognition skills.</p>
<p>This course is an excellent opportunity to refine your algorithmic thinking and prepare for those daunting coding interviews. Watch the full course on <a target="_blank" href="https://www.youtube.com/watch?v=ufBbWIyKY2E">the freeCodeCamp.org YouTube channel</a> (2-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/ufBbWIyKY2E" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is a Hash Map? Time Complexity and Two Sum Example ]]>
                </title>
                <description>
                    <![CDATA[ A hash table or hash map, is a data structure that helps with mapping keys to values for highly efficient operations like the lookup, insertion and deletion operations. In this tutorial, you'll learn the following: Constant and linear time complexit... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-a-hash-map/</link>
                <guid isPermaLink="false">66ba2fd8de9370f66eeb0aa1</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Hash tables ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mapping ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sule-Balogun Olanrewaju ]]>
                </dc:creator>
                <pubDate>Thu, 25 Jan 2024 17:02:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/joan-gamell-ZS67i1HLllo-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A hash table or hash map, is a data structure that helps with mapping keys to values for highly efficient operations like the lookup, insertion and deletion operations.</p>
<p>In this tutorial, you'll learn the following:</p>
<ul>
<li>Constant and linear time complexity.</li>
<li>Why use a hash map?</li>
<li>Things to consider when writing hash functions.</li>
<li>How to solve the Two Sum problem in PHP and JavaScript.</li>
</ul>
<h2 id="heading-what-is-constant-time-complexity-o1">What is Constant Time Complexity - O(1)?</h2>
<p>O(1) indicates that the running time of an algorithm is constant, regardless of the input size. </p>
<p>This implies that the algorithm's performance isn't dependent on the size of the input. An example is accessing an index of an array.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">constantTimeAlgorithm</span>(<span class="hljs-params">$arr</span>) 
</span>{

    <span class="hljs-keyword">echo</span> $arr[<span class="hljs-number">0</span>] . PHP_EOL;
}
</code></pre>
<p>Here is a non-code example to illustrate the concept of constant time complexity:</p>
<p>Imagine sending a file through an airline to your friend, and the airline has a policy where they charge based on the weight of the package.</p>
<p>Now, whether your file weighs 2 grams or 20 kilograms, the airline's processing time remains constant. This means that the time it takes for the airline to handle your package doesn't depend on the weight of the file – it's always the same. </p>
<p>In other words, the processing time is constant irrespective of the size of the file.</p>
<h2 id="heading-what-is-linear-time-complexity-on">What is Linear Time Complexity - O(n)?</h2>
<p>O(n) indicates that the running time of an algorithm grows linearly with the size of the input. </p>
<p>The performance of the algorithm is directly proportional to the input size. An example is traversing a <code>for</code> loop and printing elements.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">linearTimeAlgorithm</span>(<span class="hljs-params">$arr</span>) 
</span>{
    <span class="hljs-keyword">foreach</span> ($arr <span class="hljs-keyword">as</span> $element) {
        <span class="hljs-keyword">echo</span> $element . PHP_EOL;
    }
}
</code></pre>
<p>Here's a non-code example to illustrate the concept of linear time complexity:</p>
<p>Consider using an electronic transfer service to send a file to your friend. In this scenario, the time it takes to transfer the file increases linearly with the size of the file. </p>
<p>For instance, if it takes 1 minutes to transfer a 100 MB file, it would take approximately 100 minutes to transfer a 10 GB file using the same service. </p>
<p>This linear relationship between the size of the file and the time it takes to transfer it reflects linear time complexity. The time taken to transfer the file increases proportionally or linearly with the size of the input or file.</p>
<h2 id="heading-why-use-a-hash-map">Why use a Hash Map?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-108.png" alt="Image" width="600" height="400" loading="lazy">
<em>Illustration of how a hash map works</em></p>
<p>A hash map is a concrete implementation of the abstract data type known as an associative array. </p>
<p>In a hash map, keys are hashed to determine the index where the corresponding values will be stored, allowing for efficient retrieval and storage of key-value pairs. </p>
<p>This implementation typically provides fast access times for operations like insertion, deletion, and lookup of values based on their associated keys. </p>
<p>In languages like PHP or JavaScript, when you use an associative array, you are essentially using a hash map. Their associative arrays are implemented using hash tables behind the scenes. </p>
<p>You can use strings, integers, or other data types as keys, and the language's internal hashing mechanism efficiently maps these keys to their corresponding values. Additionally, JavaScript provides the <code>Map</code> object for more advanced hash map functionalities.</p>
<h3 id="heading-time-and-space-complexity-for-hash-map">Time and Space Complexity for Hash Map</h3>
<p>The time and space complexity for a hash map (or hash table) is not necessarily O(n) for all operations. The typical and desired time complexity for basic operations like insertion, lookup, and deletion in a well-designed hash map is O(1) on average. </p>
<p>Here's a breakdown of time and space complexity for a hash map:</p>
<h4 id="heading-time-complexity">Time Complexity:</h4>
<p>Average Case:</p>
<ul>
<li>Insertion (average): O(1)</li>
<li>Lookup (average): O(1)</li>
<li>Deletion (average): O(1)</li>
</ul>
<p>Worst Case:</p>
<ul>
<li>Insertion (worst): O(n), where n is the size of the hash map. This occurs when there are many hash collisions, leading to linear probing or other collision resolution strategies that may involve traversing the entire hash map.</li>
<li>Lookup and Deletion (worst): O(n), for the same reason as insertion.</li>
</ul>
<h4 id="heading-space-complexity">Space Complexity:</h4>
<ul>
<li>The space complexity is typically O(n). Where n is the number of key-value pairs stored in the hash map. Each key-value pair occupies constant space, and the space required grows linearly with the number of elements.</li>
</ul>
<p>In algorithm analysis, the notation O(1) and O(n) represent the upper bounds on the time complexity of an algorithm, where n is the size of the input.</p>
<h4 id="heading-operations">Operations</h4>
<ol>
<li><strong>Insertion:</strong> The key-value pair is hashed, and the resulting index is used to store the value in the corresponding slot. If a collision occurs, the collision resolution strategy is applied.</li>
<li><strong>Deletion:</strong> The key is hashed to find the index, and the item at that index is removed. Collision resolution may be necessary.</li>
<li><strong>Lookup:</strong> The key is hashed to find the index, and the value at that index is returned. Collision resolution may be applied if needed.</li>
</ol>
<h2 id="heading-things-to-consider-when-creating-hash-tables">Things to consider When Creating Hash Tables</h2>
<p>When creating hash tables, there are several important considerations to ensure efficiency, including fast computation of hash codes and effective collision resolution strategies.</p>
<h3 id="heading-fast-computation">Fast Computation</h3>
<p>Hash codes should be computed quickly to ensure efficient insertion, lookup, and deletion operations. A good hash function contributes to the speed of hash code computation.</p>
<h3 id="heading-avoid-collision">Avoid collision</h3>
<p>A collision happens when two or more keys produce the same hash code. In other words, multiple keys map to the same array index.</p>
<h2 id="heading-how-to-handle-collisions">How to Handle Collisions</h2>
<p>Hash maps use collision resolution techniques to deal with collisions. Common strategies include:</p>
<h4 id="heading-chaining">Chaining</h4>
<p>To manage several values with the same hash code, chaining involves storing a linked list or other data structure at each array index.  If a collision occurs, the new key-value pair is appended to the linked list at the relevant index.</p>
<h4 id="heading-open-addressing">Open addressing</h4>
<p>When a collision happens in a hash table, a technique called open addressing is employed to resolve it by searching for the next open space. </p>
<p>All it does is search the array for the next empty slot where the key-value combination can be placed. Methods including double hashing, quadratic probing, and linear probing are applied.</p>
<p><strong>Linear Probing:</strong> In linear probing, the algorithm moves linearly to the next index in the array in order to find the next open slot when a collision occurs.</p>
<p><strong>Quadratic Probing:</strong> In this method, an algorithm employs a quadratic function to find the next slot that becomes available.</p>
<p><strong>Double Hashing:</strong> In double hashing, the algorithm calculates the step size between probes using a secondary hash function.</p>
<p>In order to reduce the possibility of collisions, a good hash function should generate distinct hash codes for various inputs. By making sure the hash codes are evenly distributed throughout the range of potential values, collisions can be prevented.</p>
<h2 id="heading-how-to-solve-the-two-sum-problem">How to Solve the Two Sum Problem</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-117.png" alt="Image" width="600" height="400" loading="lazy">
<em>Two sum problem</em></p>
<p>The Two Sum problem involves finding all pairs of elements in an array that sum up to a specific target value. Now let's look at the problem statement.</p>
<h3 id="heading-problem-statement">Problem statement</h3>
<p>Given an array of integers <code>nums</code> and an integer <code>target</code>, return the indices of the two numbers such that they add up to the <code>target</code>.</p>
<p><em>Example 1:</em></p>
<p><strong>Input:</strong> nums = [3,2,4, 8], target = 12</p>
<p><strong>Output:</strong> [2, 3]</p>
<p><em>Example 2:</em></p>
<p><strong>Input:</strong> nums = [5,5], target = 10 </p>
<p><strong>Output:</strong> [0,1]</p>
<h3 id="heading-solution">Solution</h3>
<p>To solve the Two Sum problem, we can use a hash table. The idea is to traverse the <code>nums</code> array and, for each element, check if the complement (the difference between the target and the current element) is already in the hash table. If it is, we have found a pair of indices whose elements add up to the target.</p>
<p>Here are the steps to follow:</p>
<ol>
<li>To hold the elements and their respective indices, create an empty hash table upon initialization.</li>
<li>Go over the array of <code>nums</code>.</li>
<li>Do the complement calculation (target - current element) for each element.</li>
<li>Verify if the complement has already been added to the hash table.  If yes, return the current index and the index stored in the hash table for the complement.</li>
<li>If the complement is not in the hash table, store the current element and its index in the hash table.</li>
<li>If no such pair is found during the traversal, it implies that there is no solution.</li>
</ol>
<h5 id="heading-php-code-solution">PHP Code Solution</h5>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">twoSum</span>(<span class="hljs-params">$nums, $target</span>) </span>{
    $hashTable = [];

    <span class="hljs-keyword">foreach</span> ($nums <span class="hljs-keyword">as</span> $i =&gt; $num) {
        $complement = $target - $num;

        <span class="hljs-keyword">if</span> (array_key_exists($complement, $hashTable)) {

            <span class="hljs-comment">// Found the pair, return the indices</span>
            <span class="hljs-keyword">return</span> [$hashTable[$complement], $i];
        }

        <span class="hljs-comment">// Store the current element in the hash table</span>
        $hashTable[$num] = $i;
    }

    <span class="hljs-comment">// No solution found</span>
    <span class="hljs-keyword">return</span> [];
}

<span class="hljs-comment">// Example usage:</span>
$nums = [<span class="hljs-number">2</span>, <span class="hljs-number">7</span>, <span class="hljs-number">11</span>, <span class="hljs-number">5</span>, <span class="hljs-number">15</span>, <span class="hljs-number">30</span>];
$target = <span class="hljs-number">12</span>;
$result = twoSum($nums, $target);

<span class="hljs-keyword">echo</span> <span class="hljs-string">"Indices of the two numbers: ["</span> . implode(<span class="hljs-string">", "</span>, $result) . <span class="hljs-string">"]"</span>;
</code></pre>
<h5 id="heading-javascript-code-solution-using-map-function">JavaScript Code Solution using <code>map</code> Function</h5>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">twoSum</span>(<span class="hljs-params">nums, target</span>) </span>{
    <span class="hljs-keyword">const</span> hashTable = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> [index, num] <span class="hljs-keyword">of</span> nums.entries()) {
        <span class="hljs-keyword">const</span> complement = target - num;

        <span class="hljs-comment">// Check if the complement is in the Map</span>
        <span class="hljs-keyword">if</span> (hashTable.has(complement)) {

            <span class="hljs-comment">// Found the pair, return the indices</span>
            <span class="hljs-keyword">return</span> [hashTable.get(complement), index];
        }

        <span class="hljs-comment">// Store the current number and its index in the Map</span>
        hashTable.set(num, index);
    }

    <span class="hljs-comment">// No solution found</span>
    <span class="hljs-keyword">return</span> [];
}

<span class="hljs-comment">// Example usage:</span>
<span class="hljs-keyword">const</span> nums = [<span class="hljs-number">2</span>, <span class="hljs-number">7</span>, <span class="hljs-number">11</span>, <span class="hljs-number">5</span>, <span class="hljs-number">15</span>, <span class="hljs-number">30</span>];
<span class="hljs-keyword">const</span> target = <span class="hljs-number">12</span>;
<span class="hljs-keyword">const</span> result = twoSum(nums, target);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Indices of the two numbers that add up to <span class="hljs-subst">${target}</span>: [<span class="hljs-subst">${result.join(<span class="hljs-string">', '</span>)}</span>]`</span>);
</code></pre>
<p>This approach has a time complexity of O(n) because we iterate through the array once. The space complexity is also O(n) due to the storage of elements in the hash map.</p>
<h2 id="heading-resources">Resources</h2>
<ol>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Hash_table">Hash table From Wikipedia</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=RcZsTI5h0kg">Hash maps in Python</a></li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned about hash maps, things to consider when writing hash functions and a real world problem that involves solving the Two Sum problem.</p>
<p>Keep learning, and Happy Coding!</p>
<p>You can find me on <a target="_blank" href="https://www.linkedin.com/in/suleolanrewaju/">LinkedIn</a> and <a target="_blank" href="https://twitter.com/bigdevlarry">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the Sliding Window Technique – Algorithm Example and Solution ]]>
                </title>
                <description>
                    <![CDATA[ Recently, I was practicing coding problems that focused on Data Structures and Algorithms in preparation for a job change.  During this process, I came across the Sliding Window technique. I found this algorithm to be very interesting, so I wanted to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/sliding-window-technique/</link>
                <guid isPermaLink="false">66ba10f3da6e5d90e89ee191</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Arunachalam B ]]>
                </dc:creator>
                <pubDate>Thu, 11 Jan 2024 15:11:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Sliding-Window-Technique---Banner.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Recently, I was practicing coding problems that focused on Data Structures and Algorithms in preparation for a job change. </p>
<p>During this process, I came across the Sliding Window technique. I found this algorithm to be very interesting, so I wanted to share my learnings with the community. </p>
<p>This tutorial will be useful for you if you're preparing for competitive programming interviews. So, let's get started. </p>
<h2 id="heading-what-is-the-sliding-window-technique">What is the Sliding Window Technique?</h2>
<p>The sliding window technique is an algorithmic approach used in computer science and signal processing. It involves selecting a fixed-size subset, or "window," from a larger dataset and moving this window through the dataset in a step-wise fashion. </p>
<p>The window slides over the data, typically one element at a time, and performs some operation on the elements within the window at each step. </p>
<p>Are you confused? Let me elaborate on this technique with an example. </p>
<h3 id="heading-sliding-window-example">Sliding Window example</h3>
<p>Assume you're practicing for competitive programming and you encounter the following problem:</p>
<p>"Find the maximum sum of sub-array of size k with the time complexity of O(N).</p>
<p>Array = [1, 2, 6, 2, 4, 1], k = 3"</p>
<p>If you're not familiar with the concept of time complexity, here's a quick definition:</p>
<blockquote>
<p>In theoretical computer science, the time complexity is the computational complexity that describes the amount of computer time it takes to run an algorithm.</p>
</blockquote>
<p>And <a target="_blank" href="https://www.freecodecamp.org/news/learn-big-o-notation/">here's a course</a> if you'd like to learn more.</p>
<p>Back to our problem. Basically, we have to find the sub-array of size 3, whose sum is the maximum (largest number). Here's a pictorial view of how we can go about solving this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Find sum of sub-array of size k</em></p>
<h4 id="heading-manual-solution">Manual solution</h4>
<p>Let's solve it manually. From the above image, let's find the sum of each of the sub-arrays of size 3. </p>
<ul>
<li>Sum of 1st sub-array = 1 + 2 + 6 = 9</li>
<li>Sum of 2nd sub-array = 2 + 6 + 2 = 10</li>
<li>Sum of 3rd sub-array = 6 + 2 + 4 = 12</li>
<li>Sum of 4th sub-array = 2 + 4 + 1 = 7</li>
</ul>
<p>The maximum (biggest) number among 9, 10, 12, and 7 is 12 – or the 3rd sub-array. That is our solution. </p>
<h4 id="heading-code-solution">Code solution</h4>
<p>Alright, let's wear our programming shoes and try to solve this using code. </p>
<p>Here's my solution to the problem:</p>


<p>Here's a quick walk through of the above code. </p>
<p>I'm defining the input array and window size at the bottom, and calling the method <code>findMaxSumOfSequence</code> with these parameters. </p>
<p>Initially I'm doing a validation if the input array size is more than the window size, else the calculation is not possible, so return null. </p>
<p>I'm assuming the maximum sum to be negative infinity. </p>
<p>I iterate over the array, and for each item in the array, I iterate for next <code>k</code> items, find their sum, and assign the current window sum to maximum sum variable if the current window sum is more than existing maximum sum. Finally, return the maximum sum. </p>
<p>Let's try to run the code. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Find maximum sum of a sub-array of size k</em></p>
<p>Here we go. We got the right answer. </p>
<p>But, the problem does not stop here. If you look at the problem carefully, we have to find the solution in O(N) time complexity. </p>
<p>So, you might wonder what's the time complexity of the above solution. Well, the time complexity of the above solution is O(N*k). This means, we're iterating <code>k</code> times for each item in the array (nested for-loop). </p>
<p>O(N) time complexity basically describes that you have to find the maximum value by iterating over the given array only once. </p>
<h4 id="heading-using-the-sliding-window-technique">Using the Sliding Window technique</h4>
<p>How do we solve this with one iteration? Here's where sliding window technique comes into play. Let's take a look at the pictorial representation of our solution once again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sliding window technique</em></p>
<p>Here, you may notice that the window slides over the array. It's initially covering the indices 0, 1, and 2 in the 1st sub-array. For the next sub-array, it slides one-position to the right, eliminating 0th index to the left and adding the 3rd index to the right. So, now it covers the 1, 2, and 3 in the 2nd sub-array...and so on. </p>
<p>The calculation goes this way for the sub-arrays:</p>
<ul>
<li>1st sub-array = 1 + 2 + 6 = 9</li>
<li>2nd sub-array = 9 (sum of 1st sub-array) - 1 + 2 = 10</li>
</ul>
<p>Let's take a look at this carefully. We find the sum of 1st sub-array to be 9. To calculate the sum of 2nd sub-array, we subtract the number that's going out (1 at 0th index) and add the number that's coming in (2 at 3rd index). </p>
<ul>
<li>3rd sub-array = 10 (sum of 2nd sub-array) - 2 + 4 = 12</li>
<li>4th sub-array = 12 (sum of 3rd sub-array) - 6 + 1 = 7</li>
</ul>
<p>This is the sliding window technique. Following this technique, we'll able to find the sum of maximum sub-array in a single iteration. </p>
<h4 id="heading-how-to-implement-sliding-window-in-code">How to implement Sliding Window in code</h4>
<p>Alright, let's put on our coding shoes again and try to implement this. </p>


<p>Let's try to understand the above code. I made some changes to the <code>findMaxSumOfSequence</code> method. I introduced <code>start</code> and <code>end</code> variables which describe the window block. </p>
<p>In this implementation, we have 2 loops but they're not nested. This is because, in the first loop, we have to find the sum of the 1st window. The second loop will subtract and add items from the result of the first loop. </p>
<p>From the above example, the first loop will iterate over the first k items (3) which are 1, 2, and 6. I calculate the sum and store them in the <code>maxSum</code> and <code>windowSum</code> variables. </p>
<p>In the next loop, I'm iterating over each item in the array. For each item, I'm subtracting the previous number and adding the next number, and updating the result in the <code>windowSum</code> variable. I compare the <code>windowSum</code> and <code>maxSum</code> variables and update the <code>maxSum</code> variable if the <code>windowSum</code> is larger. Then I move the window to the next sub-array by incrementing the <code>start</code> and <code>end</code> variables. Finally, I return the maximum sum. </p>
<p>Here's the output of the above code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-32.png" alt="Image" width="600" height="400" loading="lazy">
<em>Find maximum sum of a sub-array of size k using sliding window technique</em></p>
<p>With this implementation, we have satisfied the problem's requirement by iterating over the array only once and finding the maximum sum of a sub-array (with O(N) time complexity). </p>
<h2 id="heading-applications-of-the-sliding-window-technique">Applications of the Sliding Window Technique</h2>
<p>The Sliding Window Technique is versatile and finds applications in various domains. </p>
<p><strong>Array and String Manipulation</strong>: In array or string processing, a sliding window can be used to efficiently perform operations such as finding subarrays or substrings that satisfy certain conditions.</p>
<p><strong>Data Compression</strong>: Sliding window compression algorithms, like LZ77 and its variants, use a window to find repeated patterns in the input data and replace them with references to previous occurrences.</p>
<p><strong>Image Processing</strong>: In image processing, a sliding window can be employed for tasks such as feature extraction, object detection, or image segmentation.</p>
<p><strong>Signal Processing</strong>: Time-series data can be analyzed using a sliding window to capture local patterns, trends, or anomalies.</p>
<p><strong>Network Protocols</strong>: Sliding window protocols are used in computer networks for reliable and efficient data transmission. The sender and receiver maintain a window of allowable sequence numbers to manage the flow of data. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Hope you now have a clear idea of how the Sliding Window Technique works after seeing these examples. I would recommend that you try to solve some other problems with this technique to get familiar with it. Trying to find the minimum sum of the sub-array of size k on your own using this technique would be a helpful exercise.</p>
<p>As I mentioned earlier, I'm actively looking to switch my job. If you have a good position available in your organization, please refer <a target="_blank" href="https://arunachalam-b.github.io/">me</a>. </p>
<p>Hope you enjoyed reading this article. If you wish to learn more about techniques to crack competitive programming interviews, subscribe to my newsletter by visiting my <a target="_blank" href="https://5minslearn.gogosoon.com/?ref=fcc_sliding_window_technique">site</a> which also has a consolidated list of all my blogs. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ K-Means Clustering – How to Unveil Hidden Patterns in Your Data ]]>
                </title>
                <description>
                    <![CDATA[ K-means clustering is a powerful technique that can help you discover hidden patterns and groupings in your datasets. Let’s look at how it works. K-means clustering is a basic but powerful tool in data science. It has changed the way we look at and u... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/k-means-clustering-unveil-hidden-patterns-in-data/</link>
                <guid isPermaLink="false">66d035ff31fbfb6c3390f1ef</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Thu, 04 Jan 2024 22:52:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/0_ZPAok0iVIVf9AfpV.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>K-means clustering is a powerful technique that can help you discover hidden patterns and groupings in your datasets. Let’s look at how it works.</p>
<p>K-means clustering is a basic but powerful tool in data science. It has changed the way we look at and understand large datasets.</p>
<p>In this article, we’ll learn about what K-means clustering is, how it works, what it’s used for, and some problems it might have. This guide is helpful and easy to understand, whether you’re learning about data science or just interested in it.</p>
<h2 id="heading-basics-of-clustering">Basics of Clustering</h2>
<p>Clustering is a way to put similar data points into groups. It helps us find patterns and shapes in data, which is very useful in areas like marketing and biology.</p>
<p>It’s a type of ‘unsupervised learning’, meaning the data forms its own groups without us knowing the answers beforehand.</p>
<p>There are many types of clustering methods like Hierarchical, Density-based, Distribution-based, and Partitioning methods. K-means falls into the category of “<a target="_blank" href="https://www.geeksforgeeks.org/partitioning-method-k-mean-in-data-mining/">partitioning methods</a>”.</p>
<h2 id="heading-what-is-k-means-clustering">What is K-Means Clustering?</h2>
<p>K-means clustering is a way to split data into groups, or ‘clusters’.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1050/0*O-Y0VC4lmAnugPOx.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image of graphs depicting data points before and after k-means clustering</em></p>
<p>We decide how many groups we want, called ‘K’. The aim is to make items in each group as similar as possible while making the groups different from each other.</p>
<p>K-means usually makes groups that are about the same size. This is different from hierarchical clustering, which can make groups of different sizes.</p>
<h2 id="heading-how-the-k-means-algorithm-works">How the K-means Algorithm Works</h2>
<p>K-means is popular because it’s a simple yet smart way of clustering data. Here’s how it works.</p>
<p>A cluster is a group of data points that are grouped together because they are similar. You will choose a number, k, which is the number of central points, called centroids, that you want in your data.</p>
<p>A centroid is a central spot that stands in the middle of a cluster. Each data point is placed into one of these clusters. This is done by minimizing the total distance within each cluster.</p>
<p>In simple terms, the K-means algorithm picks k centroids, and then assigns each data point to the closest cluster. The goal is to keep these central points, or centroids, as close together as possible.</p>
<p>Here, the term ‘means’ in K-means is about finding the average or the centroid of the data.</p>
<p>Here is a step by step approach:</p>
<ol>
<li>Pick the Number of Groups (K): First, decide how many groups you want, called ‘K’. You can choose this based on what you know or use methods like the <a target="_blank" href="https://www.geeksforgeeks.org/elbow-method-for-optimal-value-of-k-in-kmeans/">elbow method</a>.</li>
<li>Start with Centroids: Choose K points from your data randomly as starting points, called centroids.</li>
<li>Group Data Points: Put each point in your data into the nearest group, based on how close it is to the centroids.</li>
<li>Update Centroids: Change each group’s centre point to the average of all the points in that group.</li>
<li>Keep Going Until It’s Just Right: Repeat steps 3 and 4 until the groups don’t change any more.</li>
</ol>
<p>Picking the right number for K is important. If you have too many groups, it might get too complicated. If you have too few, it might be too simple.</p>
<p>If you want to see how this works in code, here is a simple example:</p>
<pre><code><span class="hljs-keyword">from</span> sklearn.cluster <span class="hljs-keyword">import</span> KMeans
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

# Step <span class="hljs-number">1</span>: Generate random data
np.random.seed(<span class="hljs-number">0</span>)
x = <span class="hljs-number">-2</span> * np.random.rand(<span class="hljs-number">100</span>, <span class="hljs-number">2</span>)  # Generate random points around (<span class="hljs-number">-2</span>, <span class="hljs-number">-2</span>)
x1 = <span class="hljs-number">1</span> + <span class="hljs-number">2</span> * np.random.rand(<span class="hljs-number">50</span>, <span class="hljs-number">2</span>)  # Generate random points around (<span class="hljs-number">3</span>, <span class="hljs-number">3</span>)
x[<span class="hljs-number">50</span>:<span class="hljs-number">100</span>, :] = x1  # Combine the two sets <span class="hljs-keyword">of</span> points

# Step <span class="hljs-number">2</span>: Visualize the data (unclustered)
plt.scatter(x[:, <span class="hljs-number">0</span>], x[:, <span class="hljs-number">1</span>], s=<span class="hljs-number">50</span>, c=<span class="hljs-string">'b'</span>)
plt.xlabel(<span class="hljs-string">'X Axis'</span>)
plt.ylabel(<span class="hljs-string">'Y Axis'</span>)
plt.show()

# Step <span class="hljs-number">3</span>: Apply KMeans clustering
kmeans = KMeans(n_clusters=<span class="hljs-number">2</span>)  # Initialize KMeans <span class="hljs-keyword">with</span> <span class="hljs-number">2</span> clusters
kmeans.fit(x)  # Fit the model to the data

# Step <span class="hljs-number">4</span>: Get the coordinates <span class="hljs-keyword">of</span> the cluster centers and the cluster labels
centroids = kmeans.cluster_centers_  # Centroids <span class="hljs-keyword">of</span> the clusters
labels = kmeans.labels_  # Labels <span class="hljs-keyword">of</span> each point

# Step <span class="hljs-number">5</span>: Visualize the clustered data
plt.scatter(x[:, <span class="hljs-number">0</span>], x[:, <span class="hljs-number">1</span>], s=<span class="hljs-number">50</span>, c=labels, cmap=<span class="hljs-string">'viridis'</span>)  # Plot data points <span class="hljs-keyword">with</span> cluster color
plt.scatter(centroids[:, <span class="hljs-number">0</span>], centroids[:, <span class="hljs-number">1</span>], s=<span class="hljs-number">200</span>, c=<span class="hljs-string">'red'</span>, marker=<span class="hljs-string">'*'</span>)  # Plot centroids
plt.xlabel(<span class="hljs-string">'X Axis'</span>)
plt.ylabel(<span class="hljs-string">'Y Axis'</span>)
plt.title(<span class="hljs-string">'K-Means Clustering'</span>)
plt.show()
</code></pre><p>Here is the final result after clustering.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:848/1*1l0nI3eCj_5Yc9tS20uFew.png" alt="Image" width="600" height="400" loading="lazy">
<em>K-means clustering</em></p>
<h2 id="heading-where-do-we-use-k-means-clustering">Where Do We Use K-Means Clustering?</h2>
<p>K-means clustering is used in many areas. Let’s look at a few of them:</p>
<h3 id="heading-market-segmentation">Market Segmentation</h3>
<p>K-means clustering is a tool businesses use to learn about their customers. It groups customers by purchases, interests, or location.</p>
<p>It is useful in retail and e-commerce for making smart marketing strategies along with recommending similar products products. A good example is Amazon’s suggestions of related items after you make a purchase.</p>
<p>This method makes customer service and product promotion more effective. It helps businesses tailor their offerings to different customer needs, improving sales and customer satisfaction.</p>
<h3 id="heading-image-compression-and-processing">Image Compression and Processing</h3>
<p>The K-means algorithm is important for working with digital images, especially when it comes to making them smaller. It does this by by grouping similar colours together and replacing them with a single colour.</p>
<p>When there are fewer colours, the image file becomes smaller, which saves storage space and makes it easier to send and use the image. This process doesn’t just make the image file smaller – it also makes the image simpler for computers to analyze.</p>
<p>This colour reduction is helpful in areas like medical imaging. Doctors often use detailed scans like MRIs to diagnose and treat illnesses. These scans show lots of tiny details, and sometimes there’s too much information. By using K-means to simplify the image, doctors can more easily see the important parts.</p>
<h3 id="heading-document-clustering-for-information-retrieval">Document Clustering for Information Retrieval</h3>
<p>K-means clustering can help manage piles of online information. It works by putting similar documents into groups. This is useful for search engines, digital libraries and other large scale document databases.</p>
<p>Imagine an online library with millions of articles. K-means can help by sorting these articles into related clusters. This can help search engines search for relevant content quickly instead of going through every single article in the database.</p>
<p>When you’re looking for something specific, K-means makes it easier and faster to find.</p>
<h3 id="heading-anomaly-detection-in-network-security">Anomaly Detection in Network Security</h3>
<p>In network security, K-means clustering is like a smart guard. It helps security teams by spotting unusual patterns in data traffic that could be signs of threats.</p>
<p>Here’s how it works: Normally, data in a network has a regular pattern. K-means looks at all this data and groups it based on these patterns. But sometimes, something strange pops up — like unexpected spikes in traffic or odd data movements. These could be clues to security risks, like hacking attempts.</p>
<p>K-means is great at quickly finding these odd patterns. It flags data that doesn’t fit into usual groups. Security teams can then check these flags to see if they’re real dangers. This quick spotting is crucial because in network security, responding fast can prevent a lot of damage.</p>
<h3 id="heading-genome-research">Genome research</h3>
<p>K-means clustering is a useful tool in gene research, especially for medical studies. It sorts genes into groups that act similarly and helps to understand genes better.</p>
<p>This grouping is valuable in personalized medicine which looks at a person’s unique genes to decide on the best treatment. K-means helps by showing which genes are alike. This way, doctors can understand the treatments that will work well for someone based on their genes.</p>
<p>So, K-means is not just about grouping genes. It’s a key part of making medicine that’s just right for each person. It helps doctors choose treatments that match a person’s genetic details, which is a big step forward in healthcare.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>K-means clustering is a powerful method for uncovering patterns in data. By grouping similar items, it helps in making data-driven decisions in various fields.</p>
<p>While it has its limitations, its ease of use and effectiveness make it a go-to method for exploratory data analysis. Whether you’re a seasoned data scientist or a curious beginner, delving into k-means clustering can open up new perspectives and insights into your data.</p>
<p>Thanks for reading this article. You can learn more at <a target="_blank" href="https://manishmshiva.com/">https://manishmshiva.com</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Binary Search – Algorithm and Time Complexity Explained ]]>
                </title>
                <description>
                    <![CDATA[ When working with arrays, you’ll often have to search through them to check if they contain a target element. You can always run a sequential search—scanning the array from the beginning to the end—on the array. But if the array is sorted, running th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/binary-search-algorithm-and-time-complexity-explained/</link>
                <guid isPermaLink="false">66bb8b1a5d242388375d386e</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ binary search ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Bala Priya C ]]>
                </dc:creator>
                <pubDate>Wed, 12 Jul 2023 14:26:58 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/cover-img-search.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When working with arrays, you’ll often have to search through them to check if they contain a target element.</p>
<p>You can always run a sequential search—scanning the array from the beginning to the end—on the array. But if the array is sorted, running the binary search algorithm is much more efficient.</p>
<p>Let's learn how binary search works, its time complexity, and code a simple implementation in Python.</p>
<h2 id="heading-how-does-linear-search-work">How Does Linear Search Work?</h2>
<p>We'll start our discussion with <strong>linear</strong> or <strong>sequential search</strong>.</p>
<p>Suppose we have an unsorted sequence of numbers <code>nums</code>. Given this nums array, you should check if the <code>target</code> is present in <code>nums</code>. You don’t have information about whether <code>nums</code> is sorted.</p>
<p>So the only way you can do this is to scan the array in a linear fashion, starting at the first element—until you find a match.</p>
<p>You can loop through the entire array to check if the element at index <code>i</code> matches the <code>target</code>. Once you find a match, you can break out of the loop.</p>
<p>Notice that in the worst case, you’ll have to scan the entire array and be lucky enough to find a match at the last index. Or you’ll have exhausted the array—without finding a match—indicating that the element is not present in the array. </p>
<p>Suppose the array has <code>n</code> elements. Because you have to scan the entire array—in the worst case—the linear search algorithm has a time complexity of O(n).</p>
<p>Here's an example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-66.png" alt="Image" width="600" height="400" loading="lazy">
<em>Linear Search Example | Image by the author</em></p>
<p>But when you do not know anything about the sequence, this is the best you can do. <em>So linear or sequential search is the best you can do when searching through unsorted sequences.</em></p>
<h3 id="heading-how-linear-search-works-in-python">How Linear Search Works in Python</h3>
<p>The function <code>linear_search</code> takes in an array <code>nums</code> and a <code>target</code> to search for. It then loops through the array sequentially to check if <code>target</code> is present in <code>nums</code>:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">linear_search</span>(<span class="hljs-params">nums,target</span>):</span>
  <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> nums:
    <span class="hljs-keyword">if</span> num == target:
      <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
  <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
</code></pre>
<p>Here are a couple of sample outputs:</p>
<pre><code class="lang-python">nums = [<span class="hljs-number">14</span>,<span class="hljs-number">21</span>,<span class="hljs-number">27</span>,<span class="hljs-number">30</span>,<span class="hljs-number">36</span>,<span class="hljs-number">2</span>,<span class="hljs-number">5</span>,<span class="hljs-number">7</span>,<span class="hljs-number">11</span>]
target = <span class="hljs-number">27</span>

print(linear_search(nums,target))
<span class="hljs-comment"># Output: True</span>

target = <span class="hljs-number">100</span>
print(linear_search(nums,target))
<span class="hljs-comment"># Output: False</span>
</code></pre>
<h2 id="heading-how-does-binary-search-work">How Does Binary Search Work?</h2>
<p>Now consider the <code>nums</code> sequence with <code>n</code> elements sorted in ascending order. For any valid index <code>k</code>, the following holds <code>True</code> for the element <code>a_k</code> at index <code>k</code>:</p>
<blockquote>
<p>The elements at indices 0, 1, 2, …, (k-1) are all less than or equal to <code>a_k</code>. And all elements at indices (k+1) to (n-1) are greater than or equal to <code>a_k</code>.</p>
</blockquote>
<p>With this information, you no longer need to run a linear scan. You can do it much faster with binary search. </p>
<p>We’re given a sorted array <code>nums</code> and a <code>target</code>. Let mid denote the middle-most index of the array and <code>nums[mid]</code> denote the element at the middle index. Here’s how the binary search algorithm works:</p>
<ul>
<li>Check if <code>nums[mid]</code> is equal to the <code>target</code>. If so, we’ve already found a match—in the very first step—and the search terminates.</li>
<li>If <code>nums[mid]</code> &gt; <code>target</code>, you <em>only</em> need to search the <em>left half</em> of the array. Even when you search through the left subarray you can use the same binary search algorithm.</li>
<li>If <code>nums[mid]</code> &lt; <code>target</code>, you can ignore all the elements up to the middle element and <em>only</em> consider the <em>right half</em> of the array.</li>
</ul>
<p>Notice that we have a recurrence relation here. First, we start by running the binary search algorithm on the array with n elements. If we don't find the target in the very first step, we run binary search on the subarray of size at most n/2 elements.</p>
<p>If we end up with an empty array or an array with one element that is <em>not</em> the <code>target</code>, we conclude that the target does not exist in the <code>nums</code> array.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-65.png" alt="Image" width="600" height="400" loading="lazy">
<em>Binary Search Example | Image by the author</em></p>
<h3 id="heading-how-to-implement-binary-search-in-python">How to Implement Binary Search in Python</h3>
<p>Here's a recursive implementation of binary search in Python:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">binary_search</span>(<span class="hljs-params">nums,target,low,high</span>):</span>
  <span class="hljs-keyword">if</span> low &gt; high:
    <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span>
  <span class="hljs-keyword">else</span>:
    mid = (low + high)//<span class="hljs-number">2</span>
    <span class="hljs-keyword">if</span> nums[mid] == target:
      <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
    <span class="hljs-keyword">elif</span> nums[mid] &lt; target:
      <span class="hljs-keyword">return</span> binary_search(nums,target,mid+<span class="hljs-number">1</span>,high)
    <span class="hljs-keyword">else</span>:
      <span class="hljs-keyword">return</span> binary_search(nums,target,low,mid<span class="hljs-number">-1</span>)
</code></pre>
<p>With a few sample runs of the <code>binary_search</code> function:</p>
<pre><code class="lang-python">nums = [<span class="hljs-number">2</span>,<span class="hljs-number">5</span>,<span class="hljs-number">7</span>,<span class="hljs-number">11</span>,<span class="hljs-number">14</span>,<span class="hljs-number">21</span>,<span class="hljs-number">27</span>,<span class="hljs-number">30</span>,<span class="hljs-number">36</span>]
target = <span class="hljs-number">27</span>

print(binary_search(nums,target,<span class="hljs-number">0</span>,len(nums)<span class="hljs-number">-1</span>))
<span class="hljs-comment"># Output: True</span>

target = <span class="hljs-number">38</span>
print(binary_search(nums,target,<span class="hljs-number">0</span>,len(nums)<span class="hljs-number">-1</span>))
<span class="hljs-comment"># Output: False</span>
</code></pre>
<h2 id="heading-what-is-the-time-complexity-of-binary-search">What Is the Time Complexity of Binary Search?</h2>
<p>In binary search, we know that the <em>search space is reduced by half</em> at each step and this guides us in computing the time complexity. </p>
<p>For an array with <code>n</code> elements, we check if the middle-most element matches the <code>target</code>. If so, we return <code>True</code> and terminate the search.</p>
<p>But if the middle element does not match the <code>target</code>, we perform binary search on a subarray of size at most <code>n/2</code>. In the next step, we have to search through an array of size at most <code>n/4</code>. And we continue this recursively until we can make a decision in a constant time (when the subarray is empty). </p>
<p>At step <code>k</code>, we need to search through an array of size at most <code>n/(2^k)</code>. And we need to find the smallest such <code>k</code> for which we have no subarray to search through.</p>
<p>Mathematically:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/image-68.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The time complexity of binary search is, therefore, <strong>O(logn)</strong>. This is much more efficient than the linear time O(n), especially for large values of n.</p>
<p>For example, if the array has 1000 elements. 2^(10) = 1024. While the binary search algorithm will terminate in around 10 steps, linear search will take a thousand steps in the worst case.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>And that's a wrap. I hope you found this introduction to binary search helpful! You’ll often run into questions involving binary search in coding interviews. </p>
<p>If you’re preparing for coding interviews, check out <a target="_blank" href="https://youtu.be/Peq4GCPNC5c">10 Common Coding Interview Questions [Solved]</a> on freeCodeCamp’s YouTube channel.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is a Greedy Algorithm? Examples of Greedy Algorithms ]]>
                </title>
                <description>
                    <![CDATA[ According to the Oxford English Dictionary, "greedy" means having excessive desire for something without considering the effect or damage done. In computer science, a greedy algorithm is an algorithm that finds a solution to problems in the shortest ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/greedy-algorithms/</link>
                <guid isPermaLink="false">66d4614e38f2dc3808b7910b</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Computer Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data structures ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tantoluwa Heritage Alabi NB ]]>
                </dc:creator>
                <pubDate>Fri, 12 May 2023 17:57:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/pexels-pixabay-206627.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>According to the Oxford English Dictionary, "greedy" means having excessive desire for something without considering the effect or damage done.</p>
<p>In computer science, a greedy algorithm is an algorithm that finds a solution to problems in the shortest time possible. It picks the path that seems optimal at the moment without regard for the overall optimization of the solution that would be formed.</p>
<p>Edsger Dijkstra, a computer scientist and mathematician who wanted to calculate a minimum spanning tree, introduced the term "Greedy algorithm". Prim and Kruskal came up with optimization techniques for minimizing cost of graphs.</p>
<p>Many Greedy algorithms were developed to solve graph problems. A graph is a structure made up of edges and vertices.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/simple-graph-diagram.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Diagram of a simple graph</em></p>
<h2 id="heading-greedy-vs-not-greedy-algorithms">Greedy vs Not Greedy Algorithms</h2>
<p>An algorithm is greedy when the path picked is regarded as the best option based on a specific criterion without considering future consequences. But it typically evaluates feasibility before making a final decision. The correctness of the solution depends on the problem and criteria used.</p>
<p>Example: A graph has various weights and you are to determine the maximum value in the tree. You'd start by searching each node and checking its weight to see if it is the largest value.</p>
<p>There are two approaches to solving this problem: greedy approach or not greedy.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/example-graph.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Example graph</em></p>
<p>This graph consists of different weights and we need to find the maximum value. We'll apply the two approaches on the graph to get the solution.</p>
<h3 id="heading-greedy-approach">Greedy Approach</h3>
<p>In the images below, a graph has different numbers in its vertices and the algorithm is meant to select the vertex with the largest number.</p>
<p>Starting from vertex 6, then it's faced with two decisions – which is bigger, 3 or 4? The algorithm picks 4, and then is faced with another decision – which is bigger, 14 or 11. It selects 14, and the algorithm ends.</p>
<p>On the other hand there is a vertex labeled 20 but it is attached to vertex 3 which greedy does not consider as the best choice. It is important to select appropriate criteria for making each immediate decision.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/greedy-approach-graph.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The sample graph showing the greedy approach</em></p>
<h3 id="heading-not-greedy-approach">Not Greedy Approach</h3>
<p>The “not greedy” approach checks all options before arriving at a final solution, unlike the "greedy approach" which stops once it gets its results.</p>
<p>Starting from vertex 6, then it's faced with two decisions – which is bigger, 3 or 4? The algorithm picks 4, and then is faced with another decision – which is bigger, 14 or 11. It selects 14 and keeps it aside.</p>
<p>Then it runs the process again, starting from vertex 6. It selects the vertex with 3 and checks it. 20 is attached to the vertex 3 and the process stops. Now it compares the two results – 20 and 14. 20 is bigger, so it selects the vertex (3) that carries the largest number and the process ends.</p>
<p>This approach considers many possibilities in finding the better solution.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/non-greedy-approach-graph.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The sample graph showing the non-greedy approach</em></p>
<h2 id="heading-characteristics-of-a-greedy-algorithm">Characteristics of a Greedy Algorithm</h2>
<ul>
<li><p>The algorithm solves its problem by finding an optimal solution. This solution can be a maximum or minimum value. It makes choices based on the best option available.</p>
</li>
<li><p>The algorithm is fast and efficient with time complexity of O(n log n) or O(n). Therefore applied in solving large-scale problems.</p>
</li>
<li><p>The search for optimal solution is done without repetition – the algorithm runs once.</p>
</li>
<li><p>It is straightforward and easy to implement.</p>
</li>
</ul>
<h2 id="heading-how-to-use-greedy-algorithms">How to Use Greedy Algorithms</h2>
<p>Before applying a greedy algorithm to a problem, you need to ask two questions:</p>
<ul>
<li><p>Do you need the best option at the moment from the problem?</p>
</li>
<li><p>Do you need an optimal solution (either minimum or maximum value)?</p>
</li>
</ul>
<p>If your answer to these questions is "Yes", then a greedy algorithm is a good choice to solve your problem.</p>
<h3 id="heading-procedure">Procedure</h3>
<p>Let’s assume you have a problem with a set of numbers and you need to find the minimum value.</p>
<p>You start of by defining the constraint, which in this case is finding the minimum value. Then each number will be scanned and checked on each constraint which serves as a condition to be fulfilled. If the condition is true, the number(s) is selected and returned as the final solution.</p>
<p>Here's a flowchart representation of this process:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/greedy-algorithm-flow-chart.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Flow chart showing the process for solving a problem using greedy algorithms</em></p>
<h2 id="heading-greedy-algorithm-examples">Greedy Algorithm Examples</h2>
<h3 id="heading-problem-1-activity-selection-problem">Problem 1 : Activity Selection Problem</h3>
<p>This problem contains a set of activities or tasks that need to be completed. Each one has a start and finish time. The algorithm finds the maximum number of activities that can be done in a given time without them overlapping.</p>
<h3 id="heading-approach-to-the-problem">Approach to the Problem</h3>
<ul>
<li><p>We have a list of activities. Each has a start time and finish time.</p>
</li>
<li><p>First, we sort the activities and start time in ascending order using the finish time of each.</p>
</li>
<li><p>Then we start by picking the first activity. We create a new list to store the selected activity.</p>
</li>
<li><p>To choose the next activity, we compare the finish time of the last activity to the start time of the next activity. If the start time of the next activity is greater than the finish time of the last activity, it can be selected. If not we skip this and check the next one.</p>
</li>
<li><p>This process is repeated until all activities are checked. The final solution is a list containing the activities that can be done.</p>
</li>
</ul>
<p>The table below shows a list of activities as well as starting and finish times.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/start-and-finish-times-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The first step is to sort the finish time in ascending order and arrange the activities with respect to the result.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/start-and-finish-times-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>After sorting the activities, we select the first activity and store it in the selected activity list. In our example, the first activity is “Homework”.</p>
<p>Moving to the next activity, we check the finish time of “Homework” (5) which was the last activity selected and the starting time of “Term paper” (4). To pick an activity, the starting time of the next activity must be greater than or equal to the finish time. (4) is less than (5), so we skip the activity and move to the next.</p>
<p>The next activity “Presentation” has a starting time of (6) and it is greater than the finish time (5) of “Homework”. So we select it and add it to our list of selected activities.</p>
<p>For the next activity, we do the same checking. Finish time of “Presentation” is (10), starting time of “Volleyball practice ” is (10). We see that the starting time is equal to the finish time which satisfies one of the conditions, so we select it and add it to our list of selected activities.</p>
<p>Continuing to the next activity, the finish time of “Volleyball” practice is (12) and the starting time of “Biology lecture” is (13). We see the starting time is greater than the finish time so we select it.</p>
<p>For our last activity, the starting time for “Hangout” is (7) and the finishing time of our last activity “Biology lecture” is (14), 7 is less than 14, so we cannot select the activity. Since we are at the end of our activity list, the process ends.</p>
<p>Our final result is the list of selected activities that we can do without time overlapping: {Homework, Presentation, Volleyball practice, Biology lecture}.</p>
<h3 id="heading-code-implementation-of-the-example">Code Implementation of the Example</h3>
<p>The variable <code>&lt;data&gt;</code> stores the starting times of each activity, the finish time of each activity, and the list of tasks (or activities) to be performed.</p>
<p>The variable <code>&lt;selected_activity&gt;</code> is an empty list that will store the selected activities that can be performed.</p>
<p><code>&lt;start_position&gt;</code> shows the position the first activity which is index “0”. This will be our starting point.</p>
<pre><code class="lang-python">data = {
  <span class="hljs-string">"start_time"</span>: [<span class="hljs-number">2</span> , <span class="hljs-number">6</span> , <span class="hljs-number">4</span> , <span class="hljs-number">10</span> , <span class="hljs-number">13</span> , <span class="hljs-number">7</span>],
  <span class="hljs-string">"finish_time"</span>: [<span class="hljs-number">5</span> , <span class="hljs-number">10</span> , <span class="hljs-number">8</span> , <span class="hljs-number">12</span> , <span class="hljs-number">14</span> , <span class="hljs-number">15</span>],
  <span class="hljs-string">"activity"</span>: [<span class="hljs-string">"Homework"</span> , <span class="hljs-string">"Presentation"</span> , <span class="hljs-string">"Term paper"</span> , <span class="hljs-string">"Volleyball practice"</span> , <span class="hljs-string">"Biology lecture"</span> , <span class="hljs-string">"Hangout"</span>]
}

selected_activity =[]
start_position = <span class="hljs-number">0</span>
</code></pre>
<p>Here's a dataframe table showing the original data:</p>
<pre><code class="lang-python">Original Info

   start_time  finish_time             activity
<span class="hljs-number">0</span>           <span class="hljs-number">2</span>            <span class="hljs-number">5</span>             Homework
<span class="hljs-number">1</span>           <span class="hljs-number">6</span>           <span class="hljs-number">10</span>         Presentation
<span class="hljs-number">2</span>           <span class="hljs-number">4</span>            <span class="hljs-number">8</span>           Term paper
<span class="hljs-number">3</span>          <span class="hljs-number">10</span>           <span class="hljs-number">12</span>  Volleyball practice
<span class="hljs-number">4</span>          <span class="hljs-number">13</span>           <span class="hljs-number">14</span>      Biology lecture
<span class="hljs-number">5</span>           <span class="hljs-number">7</span>           <span class="hljs-number">15</span>              Hangout
</code></pre>
<p>Then we sort the finish time in ascending order and rearrange the start time and activity in respect to it. We target the variables by using the keys in the dictionary.</p>
<pre><code class="lang-python">tem = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span> , len(data[<span class="hljs-string">'finish_time'</span>])):
   <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span> , len(data[<span class="hljs-string">'finish_time'</span>])):
       <span class="hljs-keyword">if</span> data[<span class="hljs-string">'finish_time'</span>][i] &lt; data[<span class="hljs-string">'finish_time'</span>][j]:
           tem = data[<span class="hljs-string">'activity'</span>][i] , data[<span class="hljs-string">'finish_time'</span>][i] , data[<span class="hljs-string">'start_time'</span>][i]
           data[<span class="hljs-string">'activity'</span>][i] , data[<span class="hljs-string">'finish_time'</span>][i] , data[<span class="hljs-string">'start_time'</span>][i] = data[<span class="hljs-string">'activity'</span>][j] , data[<span class="hljs-string">'finish_time'</span>][j] , data[<span class="hljs-string">'start_time'</span>][j]
           data[<span class="hljs-string">'activity'</span>][j] , data[<span class="hljs-string">'finish_time'</span>][j] , data[<span class="hljs-string">'start_time'</span>][j] = tem
</code></pre>
<p>In the code above, we intialized <code>&lt;tem&gt;</code> to zero. We are not using the inbuilt method to sort the finish time. We are using two loops to arrange it in ascending order. <code>&lt;i&gt;</code> and <code>&lt;j&gt;</code> represent the indexes and check if values of the <code>&lt;data['finish_time'][i]&gt;</code> is less than <code>&lt;data['finish_time'][j]&gt;</code>.</p>
<p>If the condition is true, <code>&lt;tem&gt;</code> stores the values of the elements in the <code>&lt;i&gt;</code> position and swaps the corresponding element.</p>
<p>Now we print the final result, here's what we get:</p>
<pre><code class="lang-python">print(<span class="hljs-string">"Start time: "</span> , data[<span class="hljs-string">'start_time'</span>])
print(<span class="hljs-string">"Finish time: "</span> , data[<span class="hljs-string">'finish_time'</span>])
print(<span class="hljs-string">"Activity: "</span> , data[<span class="hljs-string">'activity'</span>])

<span class="hljs-comment"># Results before sorting</span>
<span class="hljs-comment"># Start time:  [2, 6, 4, 10, 13, 7]</span>
<span class="hljs-comment"># Finish time:  [5, 10, 8, 12, 14, 15]</span>
<span class="hljs-comment"># Activity:  ['Homework', 'Presentation', 'Term paper', 'Volleyball practice', 'Biology lecture', 'Hangout']</span>


<span class="hljs-comment"># Results after sorting</span>
<span class="hljs-comment"># Start time:  [2, 4, 6, 10, 13, 7]</span>
<span class="hljs-comment"># Finish time:  [5, 8, 10, 12, 14, 15]</span>
<span class="hljs-comment"># Activity:  ['Homework', 'Term paper', 'Presentation', 'Volleyball practice', 'Biology lecture', 'Hangout']</span>
</code></pre>
<p>And here's a dataframe table showing the sorted data:</p>
<pre><code class="lang-python">Sorted Info <span class="hljs-keyword">with</span> respect to finish_time

   start_time  finish_time             activity
<span class="hljs-number">0</span>       <span class="hljs-number">2</span>            <span class="hljs-number">5</span>             Homework
<span class="hljs-number">1</span>       <span class="hljs-number">4</span>            <span class="hljs-number">8</span>           Term paper
<span class="hljs-number">2</span>       <span class="hljs-number">6</span>           <span class="hljs-number">10</span>         Presentation
<span class="hljs-number">3</span>          <span class="hljs-number">10</span>           <span class="hljs-number">12</span>       Volleyball practice
<span class="hljs-number">4</span>          <span class="hljs-number">13</span>           <span class="hljs-number">14</span>         Biology lecture
<span class="hljs-number">5</span>       <span class="hljs-number">7</span>           <span class="hljs-number">15</span>          Hangout
</code></pre>
<p>After sorting the activities, we start by selecting the first activity, which is “Homework”. It has a starting index of “0” so we use the <code>&lt;start_position&gt;</code> to target the activity and append it to the empty list.</p>
<pre><code class="lang-python">selected_activity.append(data[<span class="hljs-string">'activity'</span>][start_position])
</code></pre>
<p>The condition for selecting an activity is that the start time of the next activity selected is greater than the finish time of the previous activity. If the condition is true, the selected activity is added to the <code>&lt;selected_activity&gt;</code> list.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> pos <span class="hljs-keyword">in</span> range(len(data[<span class="hljs-string">'finish_time'</span>])):
   <span class="hljs-keyword">if</span> data[<span class="hljs-string">'start_time'</span>][pos] &gt;= data[<span class="hljs-string">'finish_time'</span>][start_position]:
       selected_activity.append(data[<span class="hljs-string">'activity'</span>][pos])
       start_position = pos

print(<span class="hljs-string">f"The student can work on the following activities: <span class="hljs-subst">{selected_activity}</span>"</span>)

<span class="hljs-comment"># Results</span>
<span class="hljs-comment"># The student can work on the following activities: ['Homework', 'Presentation', 'Volleyball practice', 'Biology lecture']</span>
</code></pre>
<p>Here's what it looks like all together:</p>
<pre><code class="lang-python">data = {
  <span class="hljs-string">"start_time"</span>: [<span class="hljs-number">2</span> , <span class="hljs-number">6</span> , <span class="hljs-number">4</span> , <span class="hljs-number">10</span> , <span class="hljs-number">13</span> , <span class="hljs-number">7</span>],
  <span class="hljs-string">"finish_time"</span>: [<span class="hljs-number">5</span> , <span class="hljs-number">10</span> , <span class="hljs-number">8</span> , <span class="hljs-number">12</span> , <span class="hljs-number">14</span> , <span class="hljs-number">15</span>],
  <span class="hljs-string">"activity"</span>: [<span class="hljs-string">"Homework"</span> , <span class="hljs-string">"Presentation"</span> , <span class="hljs-string">"Term paper"</span> , <span class="hljs-string">"Volleyball practice"</span> , <span class="hljs-string">"Biology lecture"</span> , <span class="hljs-string">"Hangout"</span>]
}

selected_activity =[]
start_position = <span class="hljs-number">0</span>
<span class="hljs-comment"># sorting the items in ascending order with respect to finish time</span>
tem = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span> , len(data[<span class="hljs-string">'finish_time'</span>])):
   <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span> , len(data[<span class="hljs-string">'finish_time'</span>])):
       <span class="hljs-keyword">if</span> data[<span class="hljs-string">'finish_time'</span>][i] &lt; data[<span class="hljs-string">'finish_time'</span>][j]:
           tem = data[<span class="hljs-string">'activity'</span>][i] , data[<span class="hljs-string">'finish_time'</span>][i] , data[<span class="hljs-string">'start_time'</span>][i]
           data[<span class="hljs-string">'activity'</span>][i] , data[<span class="hljs-string">'finish_time'</span>][i] , data[<span class="hljs-string">'start_time'</span>][i] = data[<span class="hljs-string">'activity'</span>][j] , data[<span class="hljs-string">'finish_time'</span>][j] , data[<span class="hljs-string">'start_time'</span>][j]
           data[<span class="hljs-string">'activity'</span>][j] , data[<span class="hljs-string">'finish_time'</span>][j] , data[<span class="hljs-string">'start_time'</span>][j] = tem

<span class="hljs-comment"># by default, the first activity is inserted in the list of activities to be selected.</span>

selected_activity.append(data[<span class="hljs-string">'activity'</span>][start_position])
<span class="hljs-keyword">for</span> pos <span class="hljs-keyword">in</span> range(len(data[<span class="hljs-string">'finish_time'</span>])):
   <span class="hljs-keyword">if</span> data[<span class="hljs-string">'start_time'</span>][pos] &gt;= data[<span class="hljs-string">'finish_time'</span>][start_position]:
       selected_activity.append(data[<span class="hljs-string">'activity'</span>][pos])
       start_position = pos

print(<span class="hljs-string">f"The student can work on the following activities: <span class="hljs-subst">{selected_activity}</span>"</span>)
<span class="hljs-comment"># Results</span>
<span class="hljs-comment"># The student can work on the following activities: ['Homework', 'Presentation', 'Volleyball practice', 'Biology lecture']</span>
</code></pre>
<h3 id="heading-problem-2-fractional-knapsack-problem">Problem 2: Fractional Knapsack Problem</h3>
<p>A knapsack has a maximum weight, and it can only accommodate a certain set of items. These items have a weight and a value.</p>
<p>The aim is to fill the knapsack with the items that have the highest total values and do not exceed the maximum weight capacity.</p>
<h3 id="heading-approach-to-the-problem-1">Approach to the Problem</h3>
<p>There are two elements to consider: the knapsack and the items. The knapsack has a maximum weight and carries some items with a high value.</p>
<p><strong>Scenario:</strong> In a jewelry store, there are items made of gold, silver, and wood. The costliest item is gold followed by silver and then wood. If a jewerly thief comes to the store, they take gold because they will make the most profit.</p>
<p>The thief has a bag (knapsack) that they can put those items in. But there is a limit to what the thief can carry because these items can get heavy. The idea is to pick the item the makes the highest profit and fits in the bag (knapsack) without exceeding its maximum weight.</p>
<ul>
<li><p>The first step is to find the value to weight ratio of all items to know what fraction each one occupies.</p>
</li>
<li><p>We then sort these ratios in descending order (from highest to lowest ). This way we can pick the ratios with the highest number first knowing that we will make a profit.</p>
</li>
<li><p>When we pick the highest ratio, we find the corresponding weight and add it to the knapsack. There are conditions to be checked.</p>
</li>
</ul>
<p><strong>Condition 1</strong>: If the item added has a lesser weight than the maximum weight of the knapsack, more items are added until the sum of all the items in the bag are the same as the maximum weight of the knapsack.</p>
<p><strong>Condition 2</strong>: If the sum of the items’ weight in the bag is more than the maximum capacity of the knapsack, we find the fraction of the last item added. To find the fraction, we do the following:</p>
<ul>
<li><p>We find the sum of the remaining weights of the items in the knapsack. They must be less than the maximum capacity.</p>
</li>
<li><p>We find the difference between the maximum capacity of the knapsack and the sum of the remaining weights of the items and divide by the weight of the last item to be added.</p>
</li>
</ul>
<pre><code class="lang-python">Fraction =  (maximum capacity of the knapsack - sum of remaining weights) / weight of last item to be added
</code></pre>
<p>To add the weight of the last item to the knapsack, we multiply the fraction by the weight.</p>
<pre><code class="lang-python">Weight_added = weight of last item to be added  * fraction
</code></pre>
<p>When we sum up the weights of all the items it will be equal to the knapsack's maximum weight.</p>
<h3 id="heading-practical-example">Practical Example:</h3>
<p>Let's say that the maximum capacity of the knapsack is 17, and there are three items available. The first item is gold, the second item is silver, and third item is wood.</p>
<ul>
<li><p>Weight of gold is 10, the weight of silver is 6, and the weight of wood is 2</p>
</li>
<li><p>the value (profit) of gold is 40, the value (profit) of silver is 30, and the value (profit) of wood is 6.</p>
</li>
<li><p>Ratio of gold= value/weight = 40/10 = 4</p>
</li>
<li><p>Ratio of silver = value/weight=30/6 = 5</p>
</li>
<li><p>Ratio of wood = value/weight = 6/2 = 3</p>
</li>
<li><p>Arranging the ratios in descending: 5, 4, 3.</p>
</li>
<li><p>The largest ratio is 5 and we match it to the corresponding weight “6”. It points to silver.</p>
</li>
<li><p>We put silver in the knapsack first and compare it to the maximum weight which is 17. 6 is less than 17 so we have to add another item. Going back to the ratios, the second largest is “4” and it corresponds to the weight of “10” which points to gold.</p>
</li>
<li><p>Now, we put gold in the knapsack, add the weight of the silver and gold, and compare it with the knapsack weight. (6 + 10 = 16). Checking it against the maximum weight, we see that it is less. So we can take another item. We go back to the list of ratios and take the 3rd largest which is “3” and it corresponds to “2” which points to wood.</p>
</li>
<li><p>When we add wood in the knapsack, the total weight is (6 +10+2 = 18) but that is greater than our maximum weight which is 17. We take out the wood from the knapsack and we are left with gold and silver. The total sum of the two is 16 and the maximum capacity is 17. So we need a weight of 1 to make it equal. Now we apply condition 2 discussed above to find the fraction of wood to fit in the knapsack.</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/frac1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Explanation of filling the remaining space in the backpack with a fractional piece of wood</em></p>
<p>Now the knapsack is filled.</p>
<h3 id="heading-code-implementation-of-the-example-1">Code Implementation of the Example</h3>
<p>The variable <code>&lt;data&gt;</code> stores the weights of each item and the profits. The variable <code>&lt;maximum_capacity&gt;</code> stores the maximum weight of the knapsack. <code>&lt;selected_wt&gt;</code> is intialized at 0, and it will store the selected weights to be put in the knapsack. Lastly, <code>&lt;max_profit&gt;</code> is intialized as 0, it will store the values of the selected weight.</p>
<pre><code class="lang-python">data = {
    <span class="hljs-string">"weight"</span>: [<span class="hljs-number">10</span> , <span class="hljs-number">6</span> , <span class="hljs-number">2</span>],
    <span class="hljs-string">"profit"</span>:[<span class="hljs-number">40</span> , <span class="hljs-number">30</span> ,<span class="hljs-number">6</span>]
}
max_weight = <span class="hljs-number">17</span>
selected_wt = <span class="hljs-number">0</span>
max_profit = <span class="hljs-number">0</span>
</code></pre>
<p>Then we calculate the ratio of the profit to the weight. Ratio = profit/weight:</p>
<pre><code class="lang-python">ratio = [int(data[<span class="hljs-string">'profit'</span>][i] / data[<span class="hljs-string">'weight'</span>][i]) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(data[<span class="hljs-string">'profit'</span>]))]
</code></pre>
<p>Now that we have the ratio, we arrange the elements in descending order, from biggest to smallest. Then the items in weight and profit are arranged according to the positions of the sorted ratio.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(ratio)):
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(i + <span class="hljs-number">1</span> , len(ratio)):
        <span class="hljs-keyword">if</span> ratio[i] &lt; ratio[j]:
            ratio[i] , ratio[j] = ratio[j] , ratio[i]
            data[<span class="hljs-string">'weight'</span>][i] , data[<span class="hljs-string">'weight'</span>][j] = data[<span class="hljs-string">'weight'</span>][j] , data[<span class="hljs-string">'weight'</span>][i]
            data[<span class="hljs-string">'profit'</span>][i] , data[<span class="hljs-string">'profit'</span>][j] = data[<span class="hljs-string">'profit'</span>][j] , data[<span class="hljs-string">'profit'</span>][i]
</code></pre>
<p>After the weight and profit are sorted, we start choosing the items and checking the condition. We loop through the length of ratio to target the index of each item in the list. Note: all items in ratio are arranged from biggest to smallest, so the first item is the maximum value and the last item is the minimum value.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(ratio)):
</code></pre>
<p>The first item we select has the highest ratio amongst the rest and it is in index 0. Now that the first weight is selected weight, we check if it is less than maximum weight. If it is, we add items till the total weight is equal to the weight of the knapsack. The second item we select has the second highest ratio amongst the rest and it is in index 1, the arrangement is that order of selection.</p>
<p>For every selected weight, we add it to the <code>selected_wt</code> variable and their corresponding profits to the <code>max_profit</code> variable.</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> selected_wt + data[<span class="hljs-string">'weight'</span>][i] &lt;= max_weight:
          selected_wt += data[<span class="hljs-string">'weight'</span>][i]
          max_profit += data[<span class="hljs-string">'profit'</span>][i]
</code></pre>
<p>When the sum of the selected weights in the knapsack exceeds the maximum weight, we find the fraction of the weight of the last item added to make the total selected weights be equal to the maximum weight. We do this by finding the difference between the <code>max_weight</code> and the sum of the selected weights divided by the weight of the last item added.</p>
<p>The final profit made from the fraction carried is added to the <code>max_profit</code> variable. Then we return the <code>max_profit</code> as the final result.</p>
<pre><code class="lang-python">      <span class="hljs-keyword">else</span>:
          frac_wt = (max_weight - selected_wt) / data[<span class="hljs-string">'weight'</span>][i]
          frac_value = data[<span class="hljs-string">'profit'</span>][i] * frac_wt
          max_profit += frac_value
          selected_wt += (max_weight - selected_wt)
print(max_profit)
</code></pre>
<p>Bringing it all together:</p>
<pre><code class="lang-python">
data = {
    <span class="hljs-string">"weight"</span>: [<span class="hljs-number">10</span> , <span class="hljs-number">6</span> , <span class="hljs-number">2</span>],
    <span class="hljs-string">"profit"</span>:[<span class="hljs-number">40</span> , <span class="hljs-number">30</span> ,<span class="hljs-number">6</span>]
}
max_weight = <span class="hljs-number">17</span>
selected_wt = <span class="hljs-number">0</span>
max_profit = <span class="hljs-number">0</span>

<span class="hljs-comment"># finds ratio</span>
ratio = [int(data[<span class="hljs-string">'profit'</span>][i] / data[<span class="hljs-string">'weight'</span>][i]) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(data[<span class="hljs-string">'profit'</span>]))]

<span class="hljs-comment"># sort ratio in descending order, rearranges weight and profit in order of the sorted ratio</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(ratio)):
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(i + <span class="hljs-number">1</span> , len(ratio)):
        <span class="hljs-keyword">if</span> ratio[i] &lt; ratio[j]:
            ratio[i] , ratio[j] = ratio[j] , ratio[i]
            data[<span class="hljs-string">'weight'</span>][i] , data[<span class="hljs-string">'weight'</span>][j] = data[<span class="hljs-string">'weight'</span>][j] , data[<span class="hljs-string">'weight'</span>][i]
            data[<span class="hljs-string">'profit'</span>][i] , data[<span class="hljs-string">'profit'</span>][j] = data[<span class="hljs-string">'profit'</span>][j] , data[<span class="hljs-string">'profit'</span>][i]


<span class="hljs-comment"># checks if selected weight with the highest ratio is less than the maximum weight, if so it adds it to knapsack and stores the profit, select the next item.</span>
<span class="hljs-comment"># else the sum of the selected weights is more than max weight, finds fraction</span>

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(ratio)):
    <span class="hljs-keyword">if</span> selected_wt + data[<span class="hljs-string">'weight'</span>][i] &lt;= max_weight:
          selected_wt += data[<span class="hljs-string">'weight'</span>][i]
          max_profit += data[<span class="hljs-string">'profit'</span>][i]
    <span class="hljs-keyword">else</span>:
          frac_wt = (max_weight - selected_wt) / data[<span class="hljs-string">'weight'</span>][i]
          frac_value = data[<span class="hljs-string">'profit'</span>][i] * frac_wt
          max_profit += frac_value
          selected_wt += (max_weight - selected_wt)

print(<span class="hljs-string">f"The maximum profit that can be made from each item is: <span class="hljs-subst">{round(max_profit , <span class="hljs-number">2</span>)}</span> euros"</span>)
<span class="hljs-comment"># Result</span>
<span class="hljs-comment"># The maximum profit that can be made from each item is: 73.0 euros</span>
</code></pre>
<h2 id="heading-applications-of-greedy-algorithms">Applications of Greedy Algorithms</h2>
<p>There are various applications of greedy algorithms. Some of them are:</p>
<ul>
<li><p>[Minimum spanning tree](https://en.wikipedia.org/wiki/Minimum_spanning_tree#:~:text=A%20minimum%20spanning%20tree%20(MST,minimum%20possible%20total%20edge%20weight.) is without any cycles and with the minimum possible total edge weight. This tree is derived from a connected undirected graph with weights.</p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm">Dijkstra’s shortest path</a> is a search algorithm that finds the shortest path between a vertex and other vertices in a weighted graph.</p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Travelling_salesman_problem">Travelling salesman problem</a> involves finding the shortest route that visits different places only once and returns to the starting point</p>
</li>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Huffman_coding">Huffman coding</a> assigns shorter code to frequently occurring symbols and longer code to less occurring symbols. It is used to encode data efficiently.</p>
</li>
</ul>
<h2 id="heading-advantages-of-using-a-greedy-algorithm">Advantages of Using a Greedy Algorithm</h2>
<p>Greedy algorithms are quite straight forward to implement and easy to understand. They are also very efficient and have a lower complexity time of O(N * logN).</p>
<p>They're useful in solving optimization problems, returning a maximum or minimum value.</p>
<h2 id="heading-disadvantageslimitations-of-using-a-greedy-algorithm">Disadvantages/Limitations of Using a Greedy Algorithm</h2>
<p>Even though greedy algorithms are straightforward and helpful in optimization problems, they don't offer the best solutions at all times.</p>
<p>Also greedy algos only run once, so they don't check the correctness of the result produced.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Greedy algorithms are a straightforward approach to solving optimization problems, returning a minimum or maximum value.</p>
<p>This article explained some examples of greedy algorithms and the approach to tackling each problem. By understanding how a greedy algorithm problems works you can better understand dynamic programming. If you have any questions feel free to reach out to me on <a target="_blank" href="https://twitter.com/HeritageAlabi1">Twitter</a>💙.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How the Euclidean Algorithm Works – with Code Examples in Go ]]>
                </title>
                <description>
                    <![CDATA[ By Otavio Ehrenberger The Euclidean Algorithm is a well-known and efficient method for finding the greatest common divisor (GCD) of two integers. The GCD is the largest number that can divide both integers without leaving a remainder.  The algorithm ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/euclidean-algorithm-in-golang/</link>
                <guid isPermaLink="false">66d851ede0db794d56c01bf9</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ golang ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mathematics ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 08 May 2023 20:18:08 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/pexels-skitterphoto-1019470.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Otavio Ehrenberger</p>
<p>The Euclidean Algorithm is a well-known and efficient method for finding the greatest common divisor (GCD) of two integers. The GCD is the largest number that can divide both integers without leaving a remainder. </p>
<p>The algorithm is named after the ancient Greek mathematician Euclid, who presented it in his book "Elements" around 300 BCE.</p>
<p>You can use this algorithm to solve <a target="_blank" href="https://en.wikipedia.org/wiki/Diophantine_equation">Diophantine equations</a>, to tackle the <a target="_blank" href="https://en.wikipedia.org/wiki/Lattice_problem">shortest-vector problem</a> which is the foundation of <a target="_blank" href="https://en.wikipedia.org/wiki/Lattice-based_cryptography">lattice-based cryptography</a>, and also to detect common patterns of pixels in images. This is, among other things, applied to optimize rendering processes and detect different objects in images.</p>
<h2 id="heading-how-does-the-euclidean-algorithm-work">How Does the Euclidean Algorithm Work?</h2>
<p>Here's a step-by-step explanation of how the Euclidean Algorithm works:</p>
<p>Start with two positive integers, a and b, where a &gt;= b. If a &lt; b, simply swap their values. Note that this is meant for a convenient mathematical demonstration, as the implementation also works for a &lt; b.</p>
<p>Divide a by b and find the remainder, r (use the modulo operation, represented as a % b). If r is 0, the GCD is b, and the algorithm terminates.</p>
<p>If r is not 0, set a to b and b to r. Then, repeat step 2.</p>
<p>The algorithm continues to iterate until the remainder is 0. At that point, the last non-zero remainder is the GCD of the original two numbers. </p>
<p>The Euclidean Algorithm works because the GCD of two numbers remains unchanged when the larger number is replaced by its remainder when divided by the smaller number.</p>
<h3 id="heading-example-of-euclidean-algorithm">Example of Euclidean Algorithm</h3>
<p>Here's an example to illustrate the algorithm:</p>
<p>Let's find the GCD of 30 and 9:</p>
<p>a = 30, b = 9</p>
<p>Calculate the remainder: r = a % b = 30 % 9 = 3 (since 3 is not 0, continue to step 3)</p>
<p>Update the values: a = 9, b = 3</p>
<p>Calculate the new remainder: r = a % b = 9 % 3 = 0 (r is now 0)</p>
<p>The GCD of 30 and 9 is 3.</p>
<h2 id="heading-why-does-the-euclidean-algorithm-work">Why Does the Euclidean Algorithm Work?</h2>
<p>The greatest common divisor of two integers is the largest positive integer that divides both of them without leaving a remainder. So the algorithm is based on the following key property:</p>
<p><strong>If <code>a</code> and <code>b</code> are two integers, then the GCD of <code>a</code> and <code>b</code> is the same as the GCD of <code>b</code> and <code>a % b</code>, where <code>%</code> represents the modulo operator (the remainder after division)</strong>.</p>
<p>Mathematically, the key property of the algorithm can be justified using the division algorithm:</p>
<p>Let <code>a</code> and <code>b</code> be two positive integers, such that <code>a &gt;= b</code>. We can write the division algorithm as:</p>
<p><code>a = bq + r</code>, where <code>q</code> is the quotient and <code>r</code> is the remainder.</p>
<p>Now, let <code>d</code> be a common divisor of <code>a</code> and <code>b</code>. Then, <code>a = d * m1</code> and <code>b = d * m2</code> for some integers <code>m1</code> and <code>m2</code>. We can rewrite the division algorithm as:</p>
<p><code>d * m1 = (d * m2) * q + r</code>.</p>
<p>Rearranging the equation, we get:</p>
<p><code>r = d * (m1 - m2 * q)</code>.</p>
<p>Since <code>d</code> is a factor of both <code>a</code> and <code>b</code>, and <code>r</code> can also be written as a multiple of <code>d</code>, we can conclude that <code>d</code> is also a divisor of <code>r</code>. This means that the GCD of <code>a</code> and <code>b</code> is also a divisor of <code>r</code>. So, we can replace <code>b</code> with <code>r</code> and keep finding the GCD using this algorithm until <code>b</code> becomes 0.</p>
<p>The Euclidean Algorithm is particularly useful due to its efficiency and simplicity, making it easy to implement in computer algorithms and programming languages.</p>
<p>Let's see some different ways to implement it in Go:</p>
<h2 id="heading-recursive-implementation-of-the-euclidean-algorithm-in-go">Recursive Implementation of the Euclidean Algorithm in Go</h2>
<p>This implementation of the Euclidean Algorithm in Golang is a recursive version that finds the GCD of two integers. Let's go through it step by step:</p>
<p>The function is defined as <code>GCD(a, b int) int</code>. It takes two integer inputs, <code>a</code> and <code>b</code>, and returns an integer output.</p>
<p>The base case of the recursion is checked with <code>if b == 0</code>. If <code>b</code> is 0, the function returns the value of <code>a</code> as the GCD.</p>
<p>If <code>b</code> is not 0, a temporary variable <code>tmp</code> is created and assigned the value of <code>a</code>. This temporary variable is used to store the value of <code>a</code> before updating its value in the next step.</p>
<p>The values of <code>a</code> and <code>b</code> are updated as follows:</p>
<ul>
<li><code>a</code> is assigned the current value of <code>b</code>.</li>
<li><code>b</code> is assigned the value of the remainder when <code>tmp</code> (the previous value of <code>a</code>) is divided by the new value of <code>a</code> (which was <code>b</code> before the update).</li>
</ul>
<p>The function calls itself recursively with the updated values of <code>a</code> and <code>b</code> as input, <code>return GCD(a, b)</code>.</p>
<p>The algorithm continues to call itself recursively until the base case is reached, that is <code>b</code> becomes 0. At this point, the function returns the GCD, which is the value of <code>a</code>.</p>
<pre><code class="lang-go"><span class="hljs-comment">// Recursive approach:</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">GCD</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">if</span> b == <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> a
    }
    tmp := a
    a = b
    b = tmp % a
    <span class="hljs-keyword">return</span> GCD(a, b)
}
</code></pre>
<p>For example, let's say we want to find the GCD of 56 and 48:</p>
<p>First call: GCD(56, 48)</p>
<ul>
<li>Since <code>b</code> (48) is not 0, update <code>a</code> and <code>b</code>:</li>
<li><code>a</code> becomes 48</li>
<li><code>b</code> becomes 56 % 48 = 8</li>
<li>The function calls itself with the new values: GCD(48, 8)</li>
</ul>
<p>Second call: GCD(48, 8)</p>
<ul>
<li>Since <code>b</code> (8) is not 0, update <code>a</code> and <code>b</code>:</li>
<li><code>a</code> becomes 8</li>
<li><code>b</code> becomes 48 % 8 = 0</li>
<li>The function calls itself with the new values: GCD(8, 0)</li>
</ul>
<p>Third call: GCD(8, 0)</p>
<ul>
<li>Now, <code>b</code> (0) is 0, so the function returns <code>a</code> (8) as the GCD.</li>
</ul>
<h2 id="heading-iterative-implementation-of-the-euclidean-algorithm-in-go">Iterative Implementation of the Euclidean Algorithm in Go</h2>
<p>This implementation of the Euclidean Algorithm in Golang is an iterative version using a loop to find the GCD of two integers. Let's go through the code step by step:</p>
<p>The function is defined as <code>GCD(a, b int) int</code>. It takes two integer inputs, <code>a</code> and <code>b</code>, and returns an integer output.</p>
<p>A loop is used to iterate as long as <code>b</code> is not equal to 0. The loop condition is <code>b != 0</code>. Note that this <code>for</code> loop construction in Go is essentially a <code>while</code> loop in many other languages.</p>
<p>Inside the loop, the values of <code>a</code> and <code>b</code> are updated simultaneously using a tuple assignment: <code>a, b = b, a%b</code>. This line does the following:</p>
<ul>
<li><code>a</code> is assigned the current value of <code>b</code>.</li>
<li><code>b</code> is assigned the value of the remainder when <code>a</code> is divided by <code>b</code>.</li>
</ul>
<p>When the loop exits (that is, <code>b</code> becomes 0), the value of <code>a</code> is returned as the GCD.</p>
<p>The algorithm iterates until the remainder (<code>b</code>) is 0, at which point the GCD is the last non-zero remainder, which is the value of <code>a</code>.</p>
<pre><code class="lang-go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">GCD</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">for</span> b != <span class="hljs-number">0</span> {
        a, b = b, a%b
    }
    <span class="hljs-keyword">return</span> a
}
</code></pre>
<p>For example, let's say we want to find the GCD of 100 and 64:</p>
<p>Initialize <code>a</code> as 100 and <code>b</code> as 64. Check the loop condition: <code>b</code> (64) is not 0.</p>
<p>Inside the loop, update <code>a</code> and <code>b</code>:</p>
<ul>
<li><code>a</code> becomes 64</li>
<li><code>b</code> becomes 100 % 64 = 36<br>Check the loop condition again: <code>b</code> (36) is not 0.</li>
</ul>
<p>Inside the loop, update <code>a</code> and <code>b</code>:</p>
<ul>
<li><code>a</code> becomes 36</li>
<li><code>b</code> becomes 64 % 36 = 28<br>Check the loop condition again: <code>b</code> (28) is not 0.</li>
</ul>
<p>Inside the loop, update <code>a</code> and <code>b</code>:</p>
<ul>
<li><code>a</code> becomes 28</li>
<li><code>b</code> becomes 36 % 28 = 8<br>Check the loop condition again: <code>b</code> (8) is not 0.</li>
</ul>
<p>Inside the loop, update <code>a</code> and <code>b</code>:</p>
<ul>
<li><code>a</code> becomes 8</li>
<li><code>b</code> becomes 28 % 8 = 4<br>Check the loop condition again: <code>b</code> (4) is not 0.</li>
</ul>
<p>Inside the loop, update <code>a</code> and <code>b</code>:</p>
<ul>
<li><code>a</code> becomes 4</li>
<li><code>b</code> becomes 8 % 4 = 0<br>Check the loop condition again: Now, <code>b</code> (0) is 0, so the loop exits.</li>
</ul>
<p>The function returns the value of <code>a</code> (4) as the GCD.</p>
<h2 id="heading-testing-the-solutions">Testing the Solutions</h2>
<p>These tests were created by Jon Calhoun in his free <a target="_blank" href="https://courses.calhoun.io/courses/cor_algo">Go Algorithms</a> course. Assuming you defined your <code>GCD</code> function in a file named <code>gcd.go</code>, place these tests in a file named <code>gcd_test.go</code>. Read below to see how the tests will work:</p>
<p>The function <code>TestGCD</code> is defined, taking a single parameter <code>t *testing.T</code>. The <code>*testing.T</code> is a pointer to a <code>testing.T</code> object that provides methods for reporting test failures and logging additional information.</p>
<p>An array of anonymous structs is defined, called <code>tests</code>. Each struct has three fields: <code>a</code>, <code>b</code>, and <code>want</code>. These structs represent test cases, where <code>a</code> and <code>b</code> are input values for the GCD function, and <code>want</code> is the expected result (correct GCD).</p>
<p>Several test cases are defined in the <code>tests</code> array, covering different scenarios.</p>
<p>A <code>for</code> loop iterates through the <code>tests</code> array. In each iteration, a single test case (struct) is assigned to the variable <code>tc</code>.</p>
<p>The <code>t.Run</code> function is called to run a subtest for the current test case. The first argument is a formatted string that describes the test case (using the input values <code>tc.a</code> and <code>tc.b</code>). The second argument is an anonymous function that takes a <code>*testing.T</code> parameter, similar to the main test function.</p>
<p>Inside the subtest function, the GCD function is called with the input values <code>tc.a</code> and <code>tc.b</code>, and the result is assigned to the <code>got</code> variable.</p>
<p>The <code>got</code> result is compared to the expected result <code>tc.want</code>. If they are not equal, the <code>t.Fatalf</code> function is called to report the test failure and provide an error message with the incorrect result and the expected result.</p>
<p>This test function helps ensure that the GCD function works correctly for various input values and edge cases. Running this test function with the <code>go test</code> command will execute all the test cases and report any failures, which can help identify potential issues with the GCD function implementation.</p>
<pre><code class="lang-go">
<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"testing"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestGCD</span><span class="hljs-params">(t *testing.T)</span></span> {
    tests := []<span class="hljs-keyword">struct</span> {
        a, b <span class="hljs-keyword">int</span>
        want <span class="hljs-keyword">int</span>
    }{
        {<span class="hljs-number">10</span>, <span class="hljs-number">5</span>, <span class="hljs-number">5</span>},
        {<span class="hljs-number">25</span>, <span class="hljs-number">5</span>, <span class="hljs-number">5</span>},
        {<span class="hljs-number">30</span>, <span class="hljs-number">15</span>, <span class="hljs-number">15</span>},
        {<span class="hljs-number">30</span>, <span class="hljs-number">9</span>, <span class="hljs-number">3</span>},
        {<span class="hljs-number">100</span>, <span class="hljs-number">9</span>, <span class="hljs-number">1</span>},
        {
            <span class="hljs-number">2</span> * <span class="hljs-number">2</span> * <span class="hljs-number">3</span> * <span class="hljs-number">3</span> * <span class="hljs-number">5</span>,
            <span class="hljs-number">2</span> * <span class="hljs-number">3</span> * <span class="hljs-number">5</span> * <span class="hljs-number">7</span> * <span class="hljs-number">13</span>,
            <span class="hljs-number">2</span> * <span class="hljs-number">3</span> * <span class="hljs-number">5</span>,
        }, {
            <span class="hljs-number">2</span> * <span class="hljs-number">2</span> * <span class="hljs-number">3</span> * <span class="hljs-number">3</span> * <span class="hljs-number">13</span>,
            <span class="hljs-number">2</span> * <span class="hljs-number">3</span> * <span class="hljs-number">5</span> * <span class="hljs-number">7</span> * <span class="hljs-number">13</span>,
            <span class="hljs-number">2</span> * <span class="hljs-number">3</span> * <span class="hljs-number">13</span>,
        }, {
            <span class="hljs-number">2</span> * <span class="hljs-number">3</span> * <span class="hljs-number">5</span> * <span class="hljs-number">7</span> * <span class="hljs-number">11</span> * <span class="hljs-number">13</span> * <span class="hljs-number">17</span> * <span class="hljs-number">19</span>,
            <span class="hljs-number">3</span> * <span class="hljs-number">3</span> * <span class="hljs-number">7</span> * <span class="hljs-number">7</span> * <span class="hljs-number">11</span> * <span class="hljs-number">11</span> * <span class="hljs-number">17</span> * <span class="hljs-number">17</span>,
            <span class="hljs-number">3</span> * <span class="hljs-number">7</span> * <span class="hljs-number">11</span> * <span class="hljs-number">17</span>,
        },
    }
    <span class="hljs-keyword">for</span> _, tc := <span class="hljs-keyword">range</span> tests {
        t.Run(fmt.Sprintf(<span class="hljs-string">"(%v,%v)"</span>, tc.a, tc.b), <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(t *testing.T)</span></span> {
            got := GCD(tc.a, tc.b)
            <span class="hljs-keyword">if</span> got != tc.want {
                t.Fatalf(<span class="hljs-string">"GCD() = %v; want %v"</span>, got, tc.want)
            }
        })
    }
}
</code></pre>
<p>Run the tests, creating different cases as you wish:</p>
<pre><code class="lang-bash">go <span class="hljs-built_in">test</span> -v <span class="hljs-comment"># verbose flag</span>
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Hope you had a good time learning about the Euclidean algorithm and its implementation in Go. </p>
<p>If you are interested in how these clever tricks work, take a look at the field of Number Theory in mathematics, which is particularly focused on the properties of integers, especially involving prime numbers.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
