Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Thursday, March 20, 2025

Soundex: How Computers Recognize Similar-Sounding Words




Soundex Algorithm Explained | Phonetic Matching Made Simple

Soundex Algorithm: How Computers Match Similar-Sounding Words

๐Ÿ“Œ Table of Contents


Introduction

Have you ever searched for a name and still found results even when the spelling was slightly different? That’s because of phonetic algorithms like Soundex.

๐Ÿ’ก Soundex allows computers to "hear" words instead of just reading them.

What is Soundex?

Soundex is a phonetic algorithm that converts words into codes based on pronunciation. It ensures that similar-sounding words produce the same output.

  • Handles spelling variations
  • Improves search accuracy
  • Useful in historical databases

How Soundex Works

The Soundex process follows structured steps:

  1. Keep the first letter
  2. Convert letters into numeric groups
  3. Remove duplicates
  4. Pad/trim to 4 characters

Letter Mapping

B F P V → 1 C G J K Q S X Z → 2 D T → 3 L → 4 M N → 5 R → 6 Vowels → ignored

๐Ÿ“Š Mathematical Representation

We can model Soundex as a function:

$$ S(w) = L_1 + f(w_2,w_3,...,w_n) $$

Where:

  • \( L_1 \) = first letter
  • \( f \) = transformation function

Transformation Function

$$ f(w_i) = \begin{cases} digit & \text{if consonant} \\ 0 & \text{if vowel} \end{cases} $$

Final Code Constraint

$$ |Code| = 4 $$

This ensures all Soundex outputs are uniform.


Examples

Smith

$$ S → S $$ $$ M → 5, T → 3 $$

Final Code:

$$ S530 $$

Smyth

$$ S → S $$ $$ M → 5, T → 3 $$

Final Code:

$$ S530 $$
๐Ÿ’ก Both names produce identical codes → phonetic match.

๐Ÿ’ป Implementation Code

Python Example

def soundex(name): mapping = {'B':1,'F':1,'P':1,'V':1, 'C':2,'G':2,'J':2,'K':2,'Q':2,'S':2,'X':2,'Z':2, 'D':3,'T':3,'L':4,'M':5,'N':5,'R':6} first = name[0].upper() result = first for char in name[1:].upper(): if char in mapping: result += str(mapping[char]) result = result[:4].ljust(4,'0') return result

Use Cases

  • Genealogy databases
  • Search engines
  • Government records
  • Spell checking

Limitations

  • English-centric
  • Can produce false matches
  • Ignores subtle phonetics

๐ŸŽฏ Key Takeaways

  • Soundex matches words by sound
  • Produces fixed 4-character codes
  • Used in search and data matching
  • Simple but powerful

Conclusion

Soundex is one of the earliest and most influential phonetic algorithms. Even today, it remains relevant in search systems and data matching applications.

Understanding Soundex gives you insight into how computers bridge the gap between human language and machine processing.

Sunday, March 16, 2025

The Levenshtein Algorithm: How Computers Fix Your Typos




Levenshtein Algorithm Explained – Beginner to Advanced Guide

✏️ Levenshtein Algorithm – Complete Beginner Friendly Guide

Have you ever typed something wrong and still got the correct suggestion? That’s the magic of the Levenshtein Algorithm.

This guide will take you from basic understanding → math → implementation → real-world usage in a very simple and practical way.


๐Ÿ“š Table of Contents


๐Ÿง  What is the Levenshtein Algorithm?

The Levenshtein algorithm measures how different two words are.

๐Ÿ‘‰ It counts the minimum number of edits needed to convert one word into another.

Allowed operations:

  • Insert a character
  • Delete a character
  • Replace a character

๐Ÿ“Œ Simple Example

"kitten" → "sitting"

  • k → s (replace)
  • e → i (replace)
  • add g (insert)

Distance = 3


๐Ÿ“ Mathematical Explanation (Easy)

The Levenshtein distance is calculated using this formula:

\[ D(i, j) = \begin{cases} i & \text{if } j = 0 \\ j & \text{if } i = 0 \\ \min \begin{cases} D(i-1, j) + 1 \\ D(i, j-1) + 1 \\ D(i-1, j-1) + cost \end{cases} \end{cases} \]

Simple Meaning:

  • If one word is empty → distance = length of other word
  • Otherwise → take minimum of:
    • Delete
    • Insert
    • Replace
๐Ÿ’ก cost = 0 if letters match, otherwise 1

๐Ÿ“Š Matrix Method Explained

We use a table (matrix) to compute distances step-by-step.

cut
0123
c1012
a2112
t3221

Final answer is bottom-right cell → 1


๐Ÿ’ป Code Example (Python)

def levenshtein(a, b): dp = [[0]*(len(b)+1) for _ in range(len(a)+1)] ``` for i in range(len(a)+1): dp[i][0] = i for j in range(len(b)+1): dp[0][j] = j for i in range(1, len(a)+1): for j in range(1, len(b)+1): cost = 0 if a[i-1] == b[j-1] else 1 dp[i][j] = min( dp[i-1][j] + 1, dp[i][j-1] + 1, dp[i-1][j-1] + cost ) return dp[-1][-1] ``` print(levenshtein("kitten", "sitting"))

๐Ÿ–ฅ️ CLI Output

Click to View Output
Input: kitten, sitting
Output: 3

๐ŸŒ Real-World Applications

  • Spell Check – Suggest correct words
  • Search Engines – Handle typos
  • DNA Analysis – Compare sequences
  • Plagiarism Detection – Find similarity

⚠️ Limitations

  • Does not consider typo frequency
  • All edits treated equally
  • Slow for large datasets

๐Ÿ’ก Key Takeaways

  • Measures difference between strings
  • Uses insert, delete, replace operations
  • Based on dynamic programming
  • Widely used in real-world systems

๐ŸŽฏ Final Thoughts

The Levenshtein algorithm is simple but incredibly powerful. It helps machines understand human errors and fix them intelligently.

From autocorrect to search engines—it plays a key role in making technology more user-friendly.

Saturday, November 2, 2024

JavaScript Basics: Developer Console, Data Types, Variables, and Essential Functions

JavaScript Basics Guide

JavaScript Fundamentals Guide

๐Ÿ“š Table of Contents

1. JavaScript Developer Console

The Developer Console allows you to run JavaScript directly in your browser for testing and debugging.

๐Ÿ“– Learn More

Use it to test code instantly without creating files.

๐Ÿ’ป Code Example

console.log("Hello, World!");

๐Ÿ–ฅ CLI Output

> Hello, World!

2. JavaScript Data Types

Primitive data types are the building blocks of JavaScript.

๐Ÿ“– View Data Types
  • String: "Hello"
  • Number: 42
  • Boolean: true / false
  • Undefined: let x;
  • Null: let y = null;

๐Ÿ’ป Code Example

var text = "Hello";
var num = 10;
var isTrue = true;

๐Ÿ–ฅ CLI Output

> Hello
> 10
> true

3. Variables using var

The var keyword declares variables but has hoisting behavior.

๐Ÿ“– Hoisting Explained

Variables declared with var are moved to the top and initialized as undefined.

๐Ÿ’ป Code Example

console.log(name);
var name = "Bob";

๐Ÿ–ฅ CLI Output

> undefined

4. Common JavaScript Functions

๐Ÿ“– console.log()

Used for debugging.

console.log("Hello!");
๐Ÿ“– alert()

Displays popup messages.

alert("Welcome!");
๐Ÿ“– prompt()

Takes user input.

var user = prompt("Enter name");

๐Ÿ–ฅ CLI Output

> Hello!
> Welcome!
> User Input

๐Ÿงช Live Code Playground

Try JavaScript directly below:

๐Ÿง  Interactive Quiz

1. What is the output of console.log(typeof null)?

2. Which keyword has block scope?

๐Ÿ’ก Key Takeaways

  • Console helps test code quickly
  • Primitive types are core building blocks
  • var has hoisting behavior
  • Functions help debugging and interaction

Saturday, October 26, 2024

Essential DOM Methods for Accessing HTML Elements in JavaScript

The Document Object Model (DOM) is a programming interface for web documents, making it possible for JavaScript to access and interact with HTML elements. If you've ever wondered how JavaScript "talks" to HTML, this is it. Through the DOM, JavaScript can modify page content, structure, and even styling dynamically. Here, we’ll focus on some of the key methods for accessing and manipulating elements in the DOM.

Let's explore five essential DOM methods to grab HTML elements:

---

### 1. `document.getElementById()`

The `getElementById()` method is one of the most widely used DOM methods and is specifically designed to retrieve elements by their `id`. An HTML `id` is unique within a page, meaning there can only be one element with that identifier. Using `getElementById()` is both straightforward and efficient when you know the `id` of the element you need to access.

**Usage:**


const element = document.getElementById("header");


In this example, JavaScript searches for an element with the `id` of "header" and assigns it to the variable `element`. You can then modify this element or access its properties directly.

**Example:**

If we have an HTML element like this:

html
<h1 id="header">Welcome to My Blog</h1>


We can change its text content using:


document.getElementById("header").innerText = "Hello, World!";


---

### 2. `document.getElementsByClassName()`

The `getElementsByClassName()` method returns a collection (or array-like list) of elements that have a specific class name. Since multiple elements can share the same class, this method gives us access to all of them.

**Usage:**


const elements = document.getElementsByClassName("card");


In this case, `elements` will contain a list of all elements with the class name "card." Note that this method doesn’t return a single element, so if you want to interact with a specific element from this list, you’ll need to access it by its index (e.g., `elements[0]` for the first element).

**Example:**

Suppose we have the following HTML:

html
<div class="card">Item 1</div>
<div class="card">Item 2</div>
<div class="card">Item 3</div>


If we want to change the background color of all these elements, we can loop over them:


const cards = document.getElementsByClassName("card");
for (let i = 0; i < cards.length; i++) {
    cards[i].style.backgroundColor = "lightblue";
}


---

### 3. `document.getElementsByTagName()`

This method returns all elements that match a specified tag name (like `div`, `p`, `h1`, etc.). Similar to `getElementsByClassName()`, it returns a collection of elements, allowing you to target multiple elements with the same tag.

**Usage:**


const paragraphs = document.getElementsByTagName("p");


Here, `paragraphs` will hold a list of all `<p>` elements on the page.

**Example:**

Given the following HTML structure:

html
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<p>Paragraph 3</p>


If you want to add a specific style to all paragraph elements:


const paragraphs = document.getElementsByTagName("p");
for (let i = 0; i < paragraphs.length; i++) {
    paragraphs[i].style.fontWeight = "bold";
}


---

### 4. `document.querySelector()`

The `querySelector()` method is highly versatile because it uses CSS-style selectors to grab elements. However, it only returns the first element it finds that matches the specified selector. This can be particularly useful when you know there’s only one matching element, or if you only need to target the first one.

**Usage:**


const mainHeader = document.querySelector("#main-header");


In this case, we’re selecting an element with the `id` "main-header" (just like with `getElementById()`, but using CSS syntax).

**Example:**

Consider the following HTML:

html
<div class="section">
    <h2 id="main-header">Main Header</h2>
    <h2 class="sub-header">Sub Header 1</h2>
    <h2 class="sub-header">Sub Header 2</h2>
</div>


To select the first `.sub-header` and change its color:


document.querySelector(".sub-header").style.color = "green";


---

### 5. `document.querySelectorAll()`

`querySelectorAll()` is similar to `querySelector()`, but instead of returning only the first matching element, it returns a list of all elements that match the CSS selector. This allows for a lot of flexibility, as you can target any group of elements that meet the selector criteria.

**Usage:**


const allItems = document.querySelectorAll(".menu-item");


`allItems` will contain a list of all elements with the class `menu-item`.

**Example:**

Suppose we have the following HTML:

html
<ul>
    <li class="menu-item">Home</li>
    <li class="menu-item">About</li>
    <li class="menu-item">Services</li>
    <li class="menu-item">Contact</li>
</ul>


To make all menu items uppercase, we can use:


const items = document.querySelectorAll(".menu-item");
items.forEach(item => {
    item.style.textTransform = "uppercase";
});


---

### Choosing the Right DOM Method

When it comes to choosing between these methods, it all depends on your needs:

- If you need a single, unique element (like a `header` with a unique `id`), `getElementById()` is perfect.
- For multiple elements sharing a class or tag, `getElementsByClassName()` and `getElementsByTagName()` are both solid options.
- When you need flexibility with CSS selectors or need to apply a style to the first element matching a complex selector, `querySelector()` is your go-to.
- To gather a group of elements with a more complex selector (like all items with a specific class inside a specific section), `querySelectorAll()` is a highly flexible choice.

---

### Conclusion

These DOM methods give JavaScript the power to manipulate and change the HTML document on the fly. By understanding how each method works and knowing when to use them, you’ll be able to create more dynamic and interactive web experiences with ease.

Thursday, October 10, 2024

Template Inheritance: Simplifying Web Development

When building web applications, it's common to have several HTML files that share a lot of the same code. For example, elements like the header, footer, or navigation menu often appear across multiple pages. Writing the same code repeatedly in each template can quickly become a nightmare. It not only bloats the code but also makes maintaining it more difficult. That's where **template inheritance** comes in. 

Template inheritance allows you to define a **base template** that contains all the common elements. Other templates can then extend this base template and insert their own content where needed. This method reduces duplication, keeps the code clean, and speeds up the development process.

### Why You Should Use Template Inheritance

Without template inheritance, if you had to make a small change to your site’s header, you would need to manually update every single HTML file that contains it. That’s a lot of unnecessary work! By using a base template, you can make that change in one place, and it will be reflected across all the pages that inherit from it.

#### Key Benefits:
1. **Cleaner Code**: The shared layout and structure of the website go into one base template, making each individual page much shorter and more focused on its unique content.
2. **Easier Maintenance**: One place to update common elements means fewer chances for inconsistencies or errors.
3. **Faster Development**: You only need to write the common elements once, and they’ll be applied to every page that extends the base template.

### How Template Inheritance Works

Let’s say you have three pages on your website: Home, About, and Contact. All of these pages share the same header, footer, and navigation bar. Instead of repeating the code in each of these files, you would create a base template.

#### Step 1: Create the Base Template
Your base template is a general layout that includes the common sections like the header, navigation, and footer. It also provides a placeholder where the specific content of each page will go.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} My Website {% endblock %}</title>
</head>
<body>
    <header>
        <h1>Welcome to My Website</h1>
        <nav>
            <ul>
                <li><a href="/">Home</a></li>
                <li><a href="/about">About</a></li>
                <li><a href="/contact">Contact</a></li>
            </ul>
        </nav>
    </header>

    <main>
        {% block content %}
        <!-- Page-specific content will be inserted here -->
        {% endblock %}
    </main>

    <footer>
        <p>&copy; 2024 My Website</p>
    </footer>
</body>
</html>


In this example, the `{% block title %}` and `{% block content %}` are placeholders where child templates can insert their own content. 

#### Step 2: Extend the Base Template in Other Pages
Now, instead of writing a full HTML structure for each page, you simply create child templates that extend the base template and fill in the specific content for that page.

**Home Page:**


{% extends "base.html" %}

{% block title %} Home - My Website {% endblock %}

{% block content %}
    <h2>Welcome to the Home Page!</h2>
    <p>This is the homepage of our awesome site.</p>
{% endblock %}


**About Page:**


{% extends "base.html" %}

{% block title %} About Us - My Website {% endblock %}

{% block content %}
    <h2>About Our Website</h2>
    <p>Here you can learn more about who we are and what we do.</p>
{% endblock %}


**Contact Page:**


{% extends "base.html" %}

{% block title %} Contact Us - My Website {% endblock %}

{% block content %}
    <h2>Contact Us</h2>
    <p>Feel free to reach out to us anytime via our contact form.</p>
{% endblock %}


In these examples, the `extends` tag is used to inherit the base template, and the `block` tags are used to provide the page-specific content. Notice that we don’t need to repeat the header, navigation, or footer in any of these pages. All of that comes from the base template automatically.

### Making Changes is Easy

Suppose you want to update the navigation menu by adding a new link to a "Blog" section. Without template inheritance, you'd need to go into every HTML file and manually add that link to each one. However, with template inheritance, you only need to update the base template.


<nav>
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/about">About</a></li>
        <li><a href="/contact">Contact</a></li>
        <li><a href="/blog">Blog</a></li>
    </ul>
</nav>


Once this change is made in the base template, every page that extends it will automatically reflect the update.

### Conclusion

Template inheritance is a powerful feature that saves time and reduces the complexity of your code. By separating the common structure into a base template and extending it in other templates, you can make your web application more maintainable and scalable. This approach not only helps keep your code clean but also makes future updates much easier to manage.

If you're building a website with multiple pages, adopting template inheritance is a smart choice that will streamline your development process and ensure consistency across all your pages.

Sunday, October 6, 2024

Django Form Validation: Best Practices for Handling User Input

When developing web applications using Django, form validation is a crucial step to ensure that user input meets certain criteria before processing. In this blog post, we will explore how to perform validations in Django forms, focusing on key validation rules such as ensuring fields are not empty, setting a maximum character limit, and enforcing specific conditions on input. We will look at two primary methods to implement these validations: custom clean methods and Django’s built-in validators.

#### Why Validation Matters

Validation is essential in any web application. It not only enhances user experience by providing immediate feedback but also protects your application from invalid or malicious data. Proper validation helps maintain data integrity and ensures that your application behaves as expected.

#### Setting Up Your Django Form

First, let’s start by creating a simple Django form in your `forms.py` file. For this example, we will create a form that collects a name from the user and implements our validation rules.


from django import forms

class NameForm(forms.Form):
    name = forms.CharField(max_length=10)


In this form, we’ve defined a single field called `name` that can hold up to 10 characters. Now, let’s implement our validation rules.

### Custom Validations Using Clean Methods

Django allows you to define custom validation logic through the `clean` methods. This approach gives you the flexibility to implement specific rules tailored to your application’s needs.

1. **Check for Empty Fields:**
   To ensure the field is not empty, you can use the `clean_name` method. This method will automatically be called when the form is validated.

2. **Max Length Validation:**
   We can specify that the name must not exceed 10 characters directly in the form definition, but you can also check it again in the clean method for clarity.

3. **First Character Validation:**
   We will check that the first character of the name is 'd'.

Here’s how you can implement these validations:


from django import forms

class NameForm(forms.Form):
    name = forms.CharField(max_length=10)

    def clean_name(self):
        name = self.cleaned_data.get('name')

        # Check if the field is empty
        if not name:
            raise forms.ValidationError("This field cannot be empty.")

        # Check the first character
        if name[0].lower() != 'd':
            raise forms.ValidationError("The first character must be 'd'.")

        return name


In the `clean_name` method:
- We first retrieve the `name` from `cleaned_data`.
- We check if the name is empty and raise a validation error if it is.
- We then check if the first character is 'd', and again, we raise an error if it’s not.

### Using Django’s Built-In Validators

Django also provides several built-in validators that can simplify your form validation process. Instead of writing custom validation logic, you can leverage these validators to enforce rules easily.

For our example, we can use the `RegexValidator` for checking the first character and the built-in `MaxLengthValidator` for the character limit. Here’s how to set that up:


from django import forms
from django.core.validators import RegexValidator

class NameForm(forms.Form):
    name = forms.CharField(
        max_length=10,
        validators=[
            RegexValidator(
                regex=r'^d',
                message="The first character must be 'd'.",
                code='invalid_first_character',
            )
        ]
    )

    def clean_name(self):
        name = self.cleaned_data.get('name')

        # Check if the field is empty
        if not name:
            raise forms.ValidationError("This field cannot be empty.")

        return name


In this setup:
- The `RegexValidator` checks that the name starts with 'd'. If it doesn’t, it raises a validation error with a specified message.
- The `max_length` parameter already ensures that the input does not exceed 10 characters, so we do not need to check that explicitly in the `clean_name` method.

### Conclusion

Validation is a critical part of form handling in Django, ensuring that user input is both valid and secure. By implementing validation logic in your `forms.py` file, you can maintain a high level of data integrity and enhance user experience.

Whether you choose to write custom clean methods for specific validations or utilize Django's built-in validators for efficiency, both methods provide robust solutions for validating user input. In any case, the goal remains the same: to ensure that your application handles data correctly and reliably. 

With these approaches, you are well-equipped to create forms that not only collect user input but also safeguard your application from invalid data. Happy coding!

Tuesday, October 1, 2024

Getting Started with Django Models: Concepts and Examples

Django Models Deep Dive – From Basics to Scalable Architectures

๐Ÿš€ Django Models – From Basics to Real-World Scaling

This guide takes you from understanding basic Django models to building scalable, multi-region systems—all in one place.


๐Ÿ“š Table of Contents


๐Ÿ“Œ What is a Django Model?

A model is a blueprint for your database.

One model = One database table

Each attribute = One column.


๐Ÿ—️ Model Structure

from django.db import models class Post(models.Model): title = models.CharField(max_length=200) content = models.TextField() author = models.CharField(max_length=100) created_at = models.DateTimeField(auto_now_add=True)

๐Ÿ“Š Common Field Types

  • CharField → short text
  • TextField → long text
  • IntegerField → numbers
  • DateTimeField → timestamps
  • BooleanField → True/False

๐Ÿ”„ How Django Maps Models

Django converts models into SQL tables automatically.

You write Python → Django writes SQL

๐Ÿ’พ Saving Data

post = Post(title="Hello", content="World", author="Admin") post.save()

๐Ÿ” Migrations

python manage.py makemigrations python manage.py migrate

Migrations ensure database structure stays in sync with models.


๐ŸŒ Scaling Django – Multi-Region Databases

When your app grows globally, one database isn’t enough.

Solution: Split users by region (EU, US, etc.)

Conceptually:

\[ Users \rightarrow Regions \rightarrow Databases \]


๐Ÿง  Database Router Logic

The routing decision can be simplified as:

\[ DB(user) = \begin{cases} auth\_db & \text{if authentication} \\ region\_db & \text{otherwise} \end{cases} \]

This ensures:

  • Authentication is centralized
  • Data is distributed

Example Router

def db_for_read(self, model, **hints): if model._meta.app_label == 'auth': return 'auth_db'

๐Ÿ—‘️ Deleting Records

Single Record

user = User.objects.get(id=1) user.delete()

Multiple Records

User.objects.filter(is_active=False).delete()

⚠️ Safe Deletion Practices

  • Check if object exists
  • Understand cascading deletes
  • Backup critical data

๐Ÿ“ Conceptual Math (Simple)

Think of database operations like functions:

\[ Save(Data) \rightarrow Database \]

\[ Delete(ID) \rightarrow Remove(Row) \]

\[ Route(User) \rightarrow Region \]

๐Ÿ‘‰ These are not strict equations—but mental models to understand flow.

๐Ÿ’ก Key Takeaways

  • Django models define database structure
  • ORM removes need for SQL
  • Migrations track changes safely
  • Routing enables horizontal scaling
  • Deletion must be handled carefully

๐ŸŽฏ Final Thoughts

Django models are simple at first—but incredibly powerful when combined with routing, scaling, and proper data management.

Master this layer, and you control your entire backend architecture.

Friday, September 27, 2024

How to Convert Jupyter Notebook (.ipynb) to Python Script (.py)

Convert Jupyter Notebooks (.ipynb) to Python Scripts (.py)

How to Convert Jupyter Notebooks (.ipynb) to Python Scripts (.py)

In the world of data science and machine learning, Jupyter Notebooks (.ipynb) have become a popular tool for exploring data, visualizing results, and sharing insights. However, many users struggle when trying to run these notebooks in traditional Python environments like PyCharm or Pydroid.

The main challenge is that .ipynb files are structured differently than standard Python scripts (.py files). While notebooks support interactive execution and visualizations, many developers prefer scripts that integrate cleanly into projects, automation pipelines, and production environments.

Fortunately, converting Jupyter Notebooks to Python scripts is straightforward. This guide walks through several reliable methods.

Why Convert .ipynb to .py?

  1. Compatibility: Not all IDEs and environments support Jupyter Notebooks.
  2. Version Control: Python scripts are easier to track and diff using Git.
  3. Deployment: Scripts integrate more naturally into production systems.
  4. Simplicity: A linear script format removes notebook-specific overhead.

Methods to Convert .ipynb Files to .py

1. Using the Jupyter Notebook Interface

The simplest method is using the built-in Jupyter interface:

  • Open the Jupyter Notebook.
  • Click FileDownload as.
  • Select Python (.py).

The notebook will download as a Python script that can be opened in any IDE.

2. Command Line with nbconvert

For batch conversions or automation, Jupyter’s nbconvert tool is ideal.

pip install jupyter

Navigate to the directory containing your notebook and run:

jupyter nbconvert --to script your_notebook.ipynb

This generates a .py file in the same directory.

3. Using Python Code

You can programmatically convert notebooks using Python:

from nbconvert import PythonExporter
import nbformat

# Load the notebook
with open('your_notebook.ipynb') as f:
    notebook_content = nbformat.read(f, as_version=4)

# Convert to Python script
exporter = PythonExporter()
source, _ = exporter.from_notebook_node(notebook_content)

# Save to a .py file
with open('your_notebook.py', 'w') as f:
    f.write(source)

This approach is useful for automation or integration into larger workflows.

4. Online Conversion Tools

Several online tools can convert .ipynb files to .py without requiring local setup. While convenient, always consider data privacy before uploading sensitive notebooks.

5. Manual Copy-Pasting

As a fallback, you can manually copy code cells from the notebook and paste them into a Python script. This method is best reserved for very small notebooks.

Conclusion

Converting Jupyter Notebooks to Python scripts simplifies development, improves compatibility, and supports cleaner deployment workflows. Whether you prefer GUI tools, command-line utilities, automation via Python, or manual methods, there’s a conversion option for every use case.

With these techniques in hand, you can confidently transition from notebooks to scripts and make the most of your Python development environments.

Wednesday, September 25, 2024

A Step-by-Step Guide to Setting Up a Django Project

Django is a powerful web framework that simplifies the development of web applications. This blog will provide a clear summary of the essential steps to create a Django project, highlighting the sequence of activities required to set up a basic web application.

## Step 1: Creating a Django Project

To begin, you need to create a new Django project. This can be achieved by using the command line interface. The command to start a new Django project is:


django-admin startproject firstProject


This command initializes a new directory called `firstProject`, which contains the necessary files and folder structure for your Django application. This includes settings for the project, URLs, and WSGI configurations.

## Step 2: Creating an Application within the Project

Once the project is set up, the next step is to create an application. In Django, an application is a component that performs a specific function within your project. You can create an application using the following command:


python manage.py startapp firstApp


This command generates a new directory named `firstApp`, containing files like `models.py`, `views.py`, and `tests.py`, which are essential for building your application’s functionality.

## Step 3: Adding the Application to the Project

After creating your application, it needs to be added to the Django project. This is done by modifying the `settings.py` file found in the `firstProject` directory. You must include your application in the `INSTALLED_APPS` list. Open `settings.py` and add the following line:

python
'firstApp',


This inclusion informs Django that the application exists and should be considered in the project’s overall configuration.

## Step 4: Defining a View Function

Next, you will define a view function that handles the logic for displaying information to users. This function is written inside the `views.py` file in your application directory. A simple example of a view function could look like this:

python
from django.http import HttpResponse

def home(request):
    return HttpResponse("Hello, World!")


This function takes an HTTP request as input and returns an HTTP response, which in this case, simply returns the text "Hello, World!".

## Step 5: Defining URL Patterns for the View

Once you have defined a view, the next step is to connect it to a URL pattern so that it can be accessed via a web browser. This is done in the `urls.py` file within your application directory. You need to map a URL to your view function. Here's how you can do it:

python
from django.urls import path
from .views import home

urlpatterns = [
    path('', home, name='home'),
]


This code creates a URL pattern that points to the `home` view function whenever the root URL is accessed.

## Step 6: Starting the Development Server

After setting up the views and URL patterns, it's time to start the development server. This allows you to run your project locally and test its functionality. You can start the server with the following command:


python manage.py runserver


By default, the server will start on `http://127.0.0.1:8000/`. You can access this URL in your web browser to see your application in action.

## Step 7: Sending the Request

With the server running, you can send a request to your application by entering the URL in your web browser. For example, navigating to `http://127.0.0.1:8000/` will trigger the `home` view function, and you should see the message "Hello, World!" displayed on the screen.

## Conclusion

The sequence of activities outlined above provides a clear path for setting up a Django project from scratch. Each step, from creating the project and application to defining views and URL patterns, plays a crucial role in developing a functional web application. As you become more familiar with Django, you can explore additional features such as models, templates, and forms to enhance your web applications further. Happy coding!

Friday, September 13, 2024

Extracting Underscored Words Using Python Generators

Extract Words Enclosed in Underscores using Python Generators

Extract Words Enclosed in Underscores using Python

๐Ÿ“š Table of Contents

๐Ÿงฉ Problem Statement

You are given a list of strings. Some words are wrapped in underscores like _example_.

Your task is to extract only those words that start and end with underscores.

⚙️ Step-by-Step Approach

1. Combine Input Strings

We merge all strings into one large string using join() to simplify processing.

2. Split into Words

We split the combined string using spaces to get individual words.

3. Filter Words

Check if a word starts and ends with _.

4. Use Generator (yield)

Instead of returning all results at once, we use yield to produce results lazily.

๐Ÿ’ป Code Example

def get_underscored(strings):
    combined = " ".join(strings)
    for word in combined.split():
        if word.startswith("_") and word.endswith("_"):
            yield word

# Input data
strings = [
    "This is a _test_ string",
    "Another _example_ here",
    "No underscores here",
    "Check _this_ out"
]

# Collect results
result = list(get_underscored(strings))
print(result)

๐Ÿ–ฅ️ CLI Output

$ python script.py
['_test_', '_example_', '_this_']

๐Ÿง  Interactive Learning

⚡ Try It Yourself (Interactive)

Enter multiple sentences (one per line). Words wrapped with underscores will be extracted instantly.


Output:





What does yield do?

yield pauses function execution and returns a value one at a time.

This makes it memory efficient.

Why use generators?
  • Efficient for large datasets
  • Lazy evaluation
  • Better performance

๐Ÿ’ก Key Takeaways

  • Generators use yield instead of return
  • They produce values one at a time
  • Useful for memory-efficient processing
  • Great for streaming or large inputs

Saturday, August 24, 2024

Creating Unique Flashcards with a User Quiz in Python


You need to create a dictionary for flashcards where each card consists of a term and its definition. The user inputs the number of cards, then provides terms and definitions for each card. The goal is to ensure that terms and definitions are unique. After creating the dictionary, you prompt the user to guess definitions for the terms and provide feedback on whether their guesses are correct, while also identifying if their guess matches a different term's definition.


1. Input Collection:
   - Start by initializing an empty dictionary to store terms and their definitions.
   - Ask the user to input the number of cards they want to create.
   
2. Unique Term and Definition Validation:
   - For each card, prompt the user to enter a term. Check if this term already exists in the dictionary. If it does, keep asking for a new term until a unique one is provided.
   - Similarly, prompt the user to enter a definition and check if it is already associated with a different term. If it is, keep asking for a new definition until a unique one is found.

3. Storing Data:
   - Once unique term and definition are obtained, store them in the dictionary with the term as the key and the definition as the value.

4. User Quiz:
   - After all terms and definitions are entered, prompt the user to input definitions for each term.
   - Compare the provided definition with the correct definition from the dictionary. If the definition is correct, notify the user; otherwise, provide feedback with the correct definition and indicate if their guess matches a different term’s definition.

By following these steps, you ensure that each term and definition is unique and provide informative feedback based on user input.

Filtering Words by Length from Nested Sentence Lists in Python

You need to extract words from a list of sentences and filter them based on their length. Specifically, you want to create a list of words that are shorter than or equal to a given length limit, which the user will provide as input.To solve this problem:

1. Data Preparation:
   - You start with a list of lists, where each sublist contains words from different sentences.

2. Input Handling:
   - You prompt the user to enter a length limit for filtering the words.

3. Flattening the List:
   - You flatten the nested list structure into a single list that contains all the words from all the sentences. This is done to make it easier to process each word individually.

4. Filtering Words:
   - You iterate through the flattened list of words and check the length of each word.
   - If the length of a word is less than or equal to the specified limit, you add that word to a new list.

5. Output:
   - Finally, you print the list of filtered words.

The approach ensures that only words meeting the length criterion are included in the final list, making it straightforward to analyze or process these filtered words further.


Thursday, August 22, 2024

Creating a Regular Expression Pattern for Matching Vehicles Registration

You need to define a regular expression pattern to match a specific format of text. The format includes uppercase letters, digits, and spaces, and it must conform to a predefined structure. The goal is to create a pattern that can accurately identify and validate strings that follow this format. 

1. **Pattern Components**:
   - **Uppercase Letters**: The pattern begins with two uppercase letters (`[A-Z]{2}`).
   - **Optional Space**: After the letters, there may be an optional space (`\s?`).
   - **Digits**: Followed by two digits (`[0-9]{2}`).
   - **Optional Space**: Another optional space (`\s?`).
   - **Uppercase Letters**: Followed by two more uppercase letters (`[A-Z]{2}`).
   - **Optional Space**: Again, an optional space (`\s?`).
   - **Digits**: Concludes with four digits (`[0-9]{4}`).
   - **Word Boundary**: The pattern ends with a word boundary to ensure the format does not accidentally include trailing characters (`\b`).

2. **Purpose**:
   - This pattern is designed to match strings with a specific format, such as postal codes or codes that follow a similar structure. It ensures that the string consists of uppercase letters and digits arranged in a particular way, optionally separated by spaces.

The regular expression pattern defines a specific format consisting of uppercase letters, digits, and optional spaces. It is used to match strings that conform to this structure, which might be useful for validating or extracting formatted codes from text.

Tuesday, August 20, 2024

Difference Between Series and List in Python

In Python, a **Series** and a **list** serve different purposes, even though they might seem similar at first glance. Here's a breakdown of their key differences:

### 1. **Definition and Purpose**:
   - **List**: A list is a built-in Python data structure that can hold a collection of items. These items can be of any data type, including integers, strings, floats, and even other lists. Lists are ordered, mutable, and indexed.
   - **Series**: A Series is a one-dimensional labeled array provided by the Pandas library. It is similar to a column in a spreadsheet or a database table. A Series can hold data of any type and has an associated index for each data point.

### 2. **Libraries**:
   - **List**: Part of Python's core language; no additional libraries are needed.
   - **Series**: Part of the Pandas library, so you need to import Pandas to use Series.

### 3. **Indexing**:
   - **List**: Indexed by position, starting from 0. Example: `my_list[0]` retrieves the first element.
   - **Series**: Indexed by a labeled index, which can be customized. Example: `my_series['label']` retrieves the element with the label `'label'`.

### 4. **Data Manipulation**:
   - **List**: Basic operations like append, remove, and slicing are supported. Lists are not designed for complex data manipulation or analysis.
   - **Series**: Provides more advanced data manipulation capabilities, like alignment, handling missing data, statistical operations, and more. Operations on Series are vectorized, meaning they are optimized for performance and can handle large datasets efficiently.

### 5. **Performance**:
   - **List**: Not optimized for numerical operations or large datasets.
   - **Series**: Optimized for performance with large datasets and numerical operations due to its underlying NumPy array implementation.

### 6. **Homogeneity**:
   - **List**: Can store items of different data types within the same list.
   - **Series**: Typically stores elements of the same data type, although it can technically hold different data types, but this is less common and can lead to reduced performance.

### 7. **Methods and Functions**:
   - **List**: Has basic methods like `append()`, `remove()`, `sort()`, etc.
   - **Series**: Offers a wide range of methods for data analysis, such as `mean()`, `sum()`, `value_counts()`, `head()`, etc.




In summary, use a **list** for general-purpose collections of items, and use a **Series** when working with labeled data, especially when you need to perform data analysis or manipulation.

Friday, August 16, 2024

Custom Regex Matching Engine in Python

It checks whether a given string matches a specified pattern, which may include some basic regex operators like `.` (any character), `^` (start of string), `$` (end of string), `*`, `+`, `?` (repetition operators), and `\` (escape character). The code is modular, with each stage adding complexity and functionality to the regex engine. Below is a summary of the key stages and functions:

---

### **Stage 1: Basic Single-Character Matching**
- **Function:** `single_or_empty_char(regex: str, literal: str) -> bool`
- **Purpose:** Checks if a single character in the regex matches the corresponding literal character or if the regex is empty.

---

### **Stage 2: Matching Strings of Equal Length**
- **Function:** `equal_len(regex: str, literal: str) -> bool`
- **Purpose:** Recursively checks if a regex matches a literal string when both have the same length. The `.` operator matches any single character.

---

### **Stage 3: Matching Strings of Different Lengths**
- **Function:** `different_len(regex: str, literal: str) -> bool`
- **Purpose:** Handles cases where the regex and literal strings have different lengths. It allows the regex to skip characters in the literal string and continue matching.

---

### **Stage 4: Handling Start `^` and End `$` Anchors**
- **Function:** `fix_operators(regex: str, literal: str) -> bool`
- **Purpose:** Supports `^` and `$` operators that anchor the match to the start or end of the string, respectively. This function ensures that if these anchors are present, the regex matches from the beginning or end as required.

---

### **Stage 5: Repetition Operators (`*`, `+`, `?`)**
- **Sub-Functions:**
  - **`current_scenario(base: list, index: int, symbol: str, literal_len: int) -> list`:** Generates possible matching scenarios by expanding repetition operators.
  - **`find_scenarios(base: list, idx_with_meta: dict, max_len: int) -> list`:** Generates all possible regex scenarios based on repetition operators.
- **Main Function:** `repetition_operators(regex: str, literal: str, escape: dict = None) -> bool`
- **Purpose:** Handles the `*`, `+`, and `?` repetition operators by generating different matching scenarios and checking them against the literal string.

---

### **Stage 6: Escaping Special Characters**
- **Function:** `escape_operator(regex: str, string: str) -> bool`
- **Purpose:** Adds support for the `\` escape character, allowing special characters in the regex to be treated as literals. This function processes the regex string to recognize escaped characters and then delegates to the previous stages.

---

### **Main Execution**
- **Usage:** The program takes user input in the format `regex|string` and outputs whether the string matches the regex.
- **Function:** `escape_operator(regex, string) -> bool`
- **Purpose:** Acts as the entry point to the regex engine, invoking the appropriate matching logic based on the complexity of the regex.

---

### **Conclusion**
This code progressively builds a custom regex engine by implementing core regex features in stages. It supports simple literals, basic operators like `.` for any character, and anchors like `^` and `$`. It also handles more complex repetition operators (`*`, `+`, `?`) and allows for escaping special characters (`\`). This modular approach allows for easy extension and understanding of how regex matching can be implemented from scratch.

Coffee Machine Simulation in Python: Resource Management and User Interaction

Here’s a summary of the coffee machine simulation code:


1. **Constants and Drink Recipes:**
   - **WATER_UNIT, MILK_UNIT, BEANS_UNIT:** These constants represent the basic amounts of water, milk, and coffee beans required to make one drink.
   - **DRINKS Dictionary:** This contains the recipe for each type of drink (espresso, latte, cappuccino), including the price and the required amounts of water, milk, and beans.

2. **State Variables:**
   - **total_water, total_milk, total_beans, total_cups, total_money:** These variables keep track of the machine's current resources and money.

3. **Functions:**

   - **`display_machine_status()`:** Prints the current status of the machine, showing the available water, milk, beans, cups, and money.
   - **`can_make_drink(drink)`:** Checks if the machine has enough resources (water, milk, beans) to make the selected drink.
   - **`make_drink(drink)`:** Deducts the required resources from the machine and adds the drink's price to the total money.
   - **`buy_drink()`:** Prompts the user to select a drink, checks if it can be made, and processes the transaction if possible.
   - **`fill_machine()`:** Allows the user to add water, milk, beans, and cups to the machine.
   - **`take_money()`:** Empties the machine's money into the user's account.
   - **`main_menu()`:** The main loop of the program, where users can choose to buy a drink, fill the machine, take money, display the machine's status, or quit the program.

4. **Main Program:**
   - The `main_menu()` function is called when the program starts, providing a simple text-based interface for interacting with the coffee machine.

---

### **Key Concepts:**

- **Resource Management:** The code keeps track of limited resources (water, milk, beans, cups) and updates them as drinks are made or the machine is refilled.
- **User Interaction:** The user can interact with the machine through a series of text inputs, making it a simple simulation of a real coffee machine.
- **Condition Checking:** The program checks whether there are enough resources before making a drink, ensuring that operations are realistic.

This code provides a clear example of how to manage state and handle user inputs in a simple simulation. It effectively models a coffee machine’s operations, from purchasing drinks to refilling supplies and managing funds.

Thursday, August 15, 2024

Building a Tic-Tac-Toe Game: Code Structure and AI Strategies

Tic-Tac-Toe in Python – Complete Guide with AI Logic

๐ŸŽฎ Building a Tic-Tac-Toe Game in Python (With AI)

Let’s walk through how a simple Tic-Tac-Toe game evolves into something smarter—with AI that actually thinks.


๐Ÿ“š Table of Contents


๐Ÿš€ Game Initialization

The game begins with an empty board:

board = [" " for _ in range(9)]

The user selects player types:

start user medium
๐Ÿ‘‰ This defines who plays X and O.

๐Ÿ”„ Game Loop

The loop controls turn-taking:

  • X plays
  • O plays
  • Repeat until game ends

It ensures fairness and flow.


๐Ÿ‘ค Human Moves

The player inputs a position (0–8).

Validation checks:

  • Is the index valid?
  • Is the cell empty?
๐Ÿ‘‰ Prevents illegal moves and crashes.

๐Ÿค– AI Strategies

Easy AI

Random move:

random.choice(empty_cells)

Medium AI

  • Try to win
  • Block opponent
  • Pick center/corner

Hard AI

Uses advanced logic like Minimax.


๐Ÿ“ AI Decision Math (Minimax Simplified)

\[ Score = \max(\text{AI moves}) - \min(\text{Opponent moves}) \]

Explanation:

  • AI tries to maximize its score
  • Opponent tries to minimize it

Recursive evaluation:

\[ V(s) = \begin{cases} +1 & \text{if AI wins}\\ 0 & \text{draw}\\ -1 & \text{if opponent wins} \end{cases} \]

๐Ÿ‘‰ The AI simulates all possible futures before choosing a move.

๐Ÿ’ป Code Example

def is_winner(board, player): win_combinations = [ [0,1,2],[3,4,5],[6,7,8], [0,3,6],[1,4,7],[2,5,8], [0,4,8],[2,4,6] ] return any(all(board[i]==player for i in combo) for combo in win_combinations)

๐Ÿ–ฅ️ CLI Output

Click to Expand Gameplay
X | O | X
---------
O | X |  
---------
  | O | X

Result: X wins 

๐Ÿ Game End Logic

The game ends when:

  • A player wins
  • All cells are filled (draw)

This is checked after every move.


๐Ÿ’ก Key Takeaways

  • Game loop controls flow
  • AI difficulty changes behavior
  • Math (Minimax) powers smart decisions
  • Validation ensures stable gameplay

๐ŸŽฏ Final Thoughts

This Tic-Tac-Toe project may look simple, but it introduces powerful ideas—decision-making, AI strategy, and algorithmic thinking.

Once you understand this, you can scale to much more complex games.

Featured Post

How HMT Watches Lost the Time: A Deep Dive into Disruptive Innovation Blindness in Indian Manufacturing

The Rise and Fall of HMT Watches: A Story of Brand Dominance and Disruptive Innovation Blindness The Rise and Fal...

Popular Posts