Author name: Al Fahim

How Docker Containers Work: An In-Depth Look

Docker containers have become a popular choice for application deployment and management due to their flexibility, scalability, and security. In this blog post, we’ll take an in-depth look at how Docker containers work, including their creation process, communication methods, and management techniques.

Creating Docker Containers

Docker containers are created from Docker images, which are templates that contain the necessary files and instructions to run an application. When a Docker image is created, it’s pushed to a registry, such as Docker Hub, where it can be accessed and used to create containers.

To create a Docker container, you’ll need to use the Docker command-line interface (CLI) or a Docker management tool, such as Docker Desktop. The Docker CLI provides a set of commands that allow you to interact with Docker containers and images.

Here’s an example of how to create a Docker container using the Docker CLI:

docker run -it my-image /bin/bash

This command will create a new container based on the “my-image” image and open a terminal session inside the container. The “-it” flag tells Docker to allocate a pseudo-TTY and keep the container running even after the terminal session is closed.

How Docker Containers Communicate with Each Other

Docker containers communicate with each other using a technology called “networking.” Docker provides a built-in networking system that allows containers to connect to each other and the outside world.

When you create a Docker network, you can specify the IP address range, subnet, and gateway for the network. Containers connected to the same network can communicate with each other using their IP addresses.

Here’s an example of how to create a Docker network:

docker network create my-network

This command will create a new network named “my-network.” You can then connect containers to this network using the “docker network connect” command.

Simplifying Application Deployment with Docker Containers

One of the biggest advantages of using Docker containers is that they simplify application deployment. With Docker, you can package your application and its dependencies into a single container that can be run on any system that supports Docker.

This means that you can deploy your application to a variety of environments, such as on-premises servers, cloud platforms, or even edge devices. Docker containers provide a consistent and portable way to deploy applications, which can save time and reduce the risk of compatibility issues.

Managing Docker Containers

Managing Docker containers can be a complex task, especially when you have multiple containers running on a single host. Docker provides a number of tools and techniques to help you manage containers effectively.

One of the most popular Docker management tools is Docker Compose, which allows you to define and run multi-container Docker applications. Docker Compose provides a YAML configuration file that defines the services, networks, and volumes for your application.

Here’s an example of a Docker Compose file:

version: '3'
services:
  web:
    build: .
    ports:
      - "80:80"
    depends_on:
      - db
  db:
    image: postgres
    environment:
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword
    volumes:
      - dbdata:/var/lib/postgresql/data
volumes:
  dbdata:

This Docker Compose file defines two services: “web” and “db.” The “web” service is built from the current directory, which contains the application code. The “db” service uses the official PostgreSQL image and sets environment variables for the database username and password. The “db” service also mounts a volume to persist data between container restarts.

Advantages of Using Docker Containers

There are many advantages of using Docker containers for application deployment and management. Some of the benefits include:

  • Isolation: Docker containers provide a high level of isolation between applications, which means that they can run different applications or versions of the same application without conflicts.
  • Portability: Docker containers are highly portable, which means that they can be run on any system that supports Docker, regardless of the underlying hardware or operating system.
  • Efficiency: Docker containers use fewer resources than traditional virtual machines, which means

How Docker Containers Work: An In-Depth Look Read More »

Mastering Linux Commands: An Important Guide with Descriptions

In this topic, I have to show the most used Linux commands and their usages. and at the end of the blog post, I will give you a script that will create the environment to practice these commands.

If you’re new to Linux, it can be overwhelming to navigate through all the commands and tools available. However, mastering the basics can go a long way in making your Linux experience smooth and efficient. In this blog post, we’ll go through some of the essential Linux commands and their usage.

Before we get started, it’s essential to note that Linux is a command-line operating system. Unlike graphical interfaces such as Windows or macOS, Linux is entirely based on typed commands. As a result, it can seem daunting for those who are used to graphical interfaces, but it’s nothing to worry about. In fact, many developers prefer the command-line interface because of its speed and versatility.

Here are some of the basic Linux commands that every Linux user should know:

CommandDescription
pwdPrint working directory
lsList directory contents
cdChange directory
mkdirMake directory
rmRemove files or directories
cpCopy files and directories
mvMove or rename files and directories
nanoSimple text editor
catPrint file contents
grepSearch file contents
chmodChange file or directory permissions

pwd – Print working directory

The pwd command is used to print the current working directory. It’s a handy command when you’re unsure of the directory you’re currently in. To use it, simply type pwd and hit enter. The output will be the full path of the current working directory.

ls – List directory contents

The ls command lists the contents of the current directory. It’s an essential command when navigating through the file system. Typing ls in the terminal will display a list of all the files and directories in the current directory.

cd – Change directory

The cd command is used to change the current directory. To use it, simply type cd followed by the directory name you want to change to. For example, cd Documents will change the current directory to the Documents folder.

mkdir – Make directory

The mkdir command is used to create a new directory. To use it, type mkdir followed by the name of the directory you want to create. For example, mkdir MyFolder will create a new directory named MyFolder.

rm – Remove files or directories

The rm command is used to remove files or directories. It’s a powerful command, so make sure you’re using it with caution. To remove a file, simply type rm followed by the file name. For example, rm myfile.txt will delete a file named myfile.txt. At the same time, to remove a directory, you need to add the -r option, which stands for recursive. For example, rm -r MyFolder will delete the directory named MyFolder and all its contents.

cp – Copy files and directories

The cp command is used to copy files and directories. To use it, type cp followed by the source file or directory and the destination file or directory. For example, cp myfile.txt MyFolder will copy the file named myfile.txt to the directory named MyFolder.

mv – Move or rename files and directories

The mv command is used to move or rename files and directories. To use it, type mv followed by the source file or directory and the destination file or directory. For example, `mv myfile.txt

Now obviously, when working you are not going to take a look at these notes or online every time you need to copy or move. Also, at the same time you need to practice it first so that you can learn the usage by hand. That is why, I have created a shell script that will create multiple folders and files inside those folders. To use that, simply copy the code and save that in a file. Make sure the extension of the file is .sh so the file name would look like generator.sh. Then in that folder run the command ./generator.sh` . The shell script will create 3 different folders and inside the folder, there will be some text files.

Here is the shell script. I will add some task below the shell script so that you can practice on your own.

#!/bin/bash

# Create Fruits, Animal, and Continent directories
mkdir Fruits
mkdir Animal
mkdir Continent

# Create 3 text files in the Fruits directory
echo "Creating text files in the Fruits directory..."
touch Fruits/mango.txt
echo "Mango is a juicy and sweet tropical fruit." > Fruits/mango.txt
touch Fruits/orange.txt
echo "Oranges are citrus fruits that are high in vitamin C." > Fruits/orange.txt
touch Fruits/banana.txt
echo "Bananas are a popular fruit that are rich in potassium." > Fruits/banana.txt

# Create 5 text files in the Animal directory
echo "Creating text files in the Animal directory..."
touch Animal/lion.txt
echo "Lions are large carnivorous cats that live in groups called prides." > Animal/lion.txt
touch Animal/elephant.txt
echo "Elephants are the largest land animals on Earth and have a remarkable memory." > Animal/elephant.txt
touch Animal/giraffe.txt
echo "Giraffes are the tallest mammals in the world, with long necks and legs." > Animal/giraffe.txt
touch Animal/zebra.txt
echo "Zebras are herbivorous animals with black and white stripes." > Animal/zebra.txt
touch Animal/hippo.txt
echo "Hippos are semi-aquatic mammals that are known for their aggressive behavior." > Animal/hippo.txt

# Create 7 text files in the Continent directory
echo "Creating text files in the Continent directory..."
touch Continent/asia.txt
echo "Asia is the largest continent in the world and is home to many diverse cultures." > Continent/asia.txt
touch Continent/africa.txt
echo "Africa is the second-largest continent in the world and is known for its wildlife and natural resources." > Continent/africa.txt
touch Continent/europe.txt
echo "Europe is a continent that is rich in history and has many famous landmarks." > Continent/europe.txt
touch Continent/north_america.txt
echo "North America is the third-largest continent in the world and is home to many different countries and cultures." > Continent/north_america.txt
touch Continent/south_america.txt
echo "South America is a continent that is known for its vibrant cultures, music, and food." > Continent/south_america.txt
touch Continent/australia.txt
echo "Australia is the smallest continent in the world and is known for its unique wildlife, such as kangaroos and koalas." > Continent/australia.txt
touch Continent/antarctica.txt
echo "Antarctica is the coldest continent in the world and is mostly covered in ice." > Continent/antarctica.txt

echo "Folders and files created successfully!"

Practice Questions

Level: Easy

  • Use cd to go into the folder fruits
  • Use pwd to print the directory
  • Show the list of files in that fruits folder (use ls)
  • Create a new folder inside the fruits folder called backup_files (use mkdir)
  • Copy banana.txt file inside the backup_files directory
  • Move the mango.txt file inside the backup_files directory
  • remove banana.txt file from the fruits directory.

Level: Intermediate

  • go to animal directory and list out all the files including their permission level
    • hintUse the ls -a to see the permission level
  • Create a directory called backup and copy all the files in that directory
  • remove zebra.txt from the backup directory only

Level: hard

  • Go to continent directory and list out all the files including their permission level
  • create a folder called africa
  • move the africa.txt file inside the africa
  • copy the files elephant.txt hippo.txt and zebra.txt into the africa folder
  • create another folder asia inside the continent folder.
  • copy mango.txt and lion.txt to the asia folder.

That’s it for today. I will talk about the nano cat grep and chmod in a separate post. If you are here till now, please like and share my post with others. Thank you.

Mastering Linux Commands: An Important Guide with Descriptions Read More »

7 Powerful NGINX Configurations To Run Web Server as You Wanted

nGinx is a very powerful webserver which we can configure to our needs. Over the time, in various situations, I have used nGinx to act as reverse proxy, load balancer etc. I have tried to create a note of those configuration so that I can take a look at them whenever I need them. Here are these configurations

Reverse Proxy Configuration

A reverse proxy server is a server that sits in front of web servers and directs client requests to the appropriate web server. This configuration can be used to improve the security, scalability, and reliability of web applications.

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

we have defined an upstream block that defines two servers for load balancing. We have also defined a server block that listens on port 80 and directs traffic to the backend servers using the proxy_pass directive.

SSL/TLS Configuration

SSL/TLS is a protocol that encrypts data sent over the internet. This configuration can be used to improve the security of web applications. Here we have defined a server block that listens on port 443 with SSL/TLS enabled. We have also defined the SSL certificate and key files using the ssl_certificate and ssl_certificate_key directives

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Caching Configuration

Caching is a technique that stores frequently accessed data in memory to improve performance. This configuration can be used to improve the performance of web applications.

http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m;

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_cache my_cache;
            proxy_cache_valid 200 60m;
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this configuration, we have defined a cache path and zone using the proxy_cache_path directive. We have also defined a server block that uses the proxy_cache directive to cache frequently accessed data.

Securing nGinx

Rate Limiting

Rate limiting is a technique that limits the number of requests that can be made within a certain period of time. This can be used to prevent abuse and protect against DDoS attacks.

http {
    limit_req_zone $binary_remote_addr zone=my_zone:10m rate=1r/s;

    server {
        listen 80;
        server_name example.com;

        location / {
            limit_req zone=my_zone;
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

here, we have defined a limit_req_zone using the $binary_remote_addr variable to track requests from each IP address. We have also defined a server block that uses the limit_req directive to limit requests to 1 request per second.

IP Blocking

IP blocking is a technique that blocks access from specific IP addresses. This can be used to prevent access from known attackers or malicious users. Here, we have defined a deny directive to block access from the IP address 192.168.0.1. We have also defined a server block that allows access to all other IP addresses.

http {
    deny 192.168.0.1;

    server {
        listen 80;
        server_name example.com;

        location / {
            allow all;
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

Request Filtering

Request filtering is a technique that blocks requests that match certain patterns. This can be used to prevent access to sensitive files or prevent SQL injection attacks.

http {
    server {
        listen 80;
        server_name example.com;

        location / {
            if ($request_uri ~* "(.*/)?\.git(/.*)?$") {
                return 403;
            }
            if ($query_string ~* "union.*select.*\(") {
                return 403;
            }
            proxy_pass http://localhost:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

In this configuration, we have defined two if statements to block requests that match certain patterns. The first if statement blocks requests that contain the “.git” string in the request URI, which can prevent access to sensitive Git repository files. The second if statement blocks requests that contain the “union select” string in the query string, which can prevent SQL injection attacks.

Creating a Load Balancer

To create a load balancer using nginx, we can use the upstream block and the proxy_pass directive as shown in the load balancer configuration above. We can define multiple servers in the upstream block and nginx will distribute incoming traffic across them.

upstream backend {
    server 192.168.0.10;
    server 192.168.0.11;
}

In this upstream block, we have defined two servers with IP addresses 192.168.0.10 and 192.168.0.11. We can then use the proxy_pass directive in the server block to direct traffic to the upstream servers.

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

In this server block, we have defined the listen directive to port 80 and set the server_name directive to example.com. We have also defined a location block that uses the proxy_pass directive to direct traffic to the upstream servers defined in the backend upstream block.

7 Powerful NGINX Configurations To Run Web Server as You Wanted Read More »

Featured image for the post the power of refactoring

The Power of Refactoring: Transforming a Dashboard for Improved Load Time

In this post I am going to share an experience about refactoring a project that decreased the load time of a website.

Brief History

A few years ago, I was working on a project where I was tasked to improve the performance of a certain dashboard. Before I tell you the problem with the dashboard, let me tell you what it looked like. Mainly it was a mash-up of multiple charts to show some data points. When the page loaded, it used to show a loading screen and in the background, it used to make one single request to fetch those data. The backend would then query the database couple of times to generate around seven different data points (yes, because that’s how many charts were there). Once all the querying is completed it would return back the results to the front. It used to take around 10-12 seconds before we could see anything on the website. To put the cherry on top, it was the first page for an admin after the login. So even if the user wants to go to a different page for different work they had to wait before the entire page loads.

Although I am using the word frontend, it is not like a detached frontend. It’s a legacy application where each page was served by the server. However, in a few parts, the project was using JQuery to fetch a few data from API. (I did not know why some parts of the application use APIs and on the other hand some serve HTTP pages… I was not there when they made this decision).

Do we make it look faster or actually faster?

People used to complain about this dashboard a lot especially the slowness of that specific page and something had to be done. Eventually, we reached a conclusion to make that part faster!! Now here is the thing, you can either make things faster or you can make people feel that the site is getting faster. And we needed both. This requires a lot of refactoring.

A frontend framework for the reactive dashboard

To further improve the performance of the dashboard, we decided to use Vue.js to render the dashboard. Using Vue.js, we can take advantage of its reactive components to render the page quickly and provide an improved user experience. Additionally, Vue.js allows us to use virtual DOM, which helps to reduce the time taken to render the page. This allows us to update the page faster, providing users with a more responsive experience. Furthermore, Vue.js provides a number of features that can be used to further improve the performance of the dashboard, such as server-side rendering and code-splitting.

By using Vue.js to render the dashboard, we can ensure that the page is rendered quickly and efficiently, giving users a better experience. Now a lot of you might say, we could’ve used React or even Svelt instead of VueJS, but at that time, some of our devs knew vueJS a little bit more than any other frameworks. Which is why we choose that. Plus their way of making any page a vue app just by adding the CDN link was extra beneficial. That’s why we choose that.

Image about the power of refactoring for faster dashboard

the power of refactoring for faster dashboard

Splitting APIs

To further enhance the performance of the dashboard, we have employed a strategy of splitting the data into multiple APIs as opposed to serving it all together. This approach has allowed us to retrieve only the data that is necessary for the user, thus reducing the load time of the page. Moreover, the division of the data into multiple APIs has enabled us to reduce the processing time of the data, again leading to improved performance of the page. At the same time, we have been able to take advantage of caching, which allows us to store the data and serve it quickly, thereby reducing the time taken to render the page. In this way, we are able to ensure that users have access to the data in a rapid and efficient manner.

Change in UI to make it faster

The first approach was to serve an empty dashboard page when the user was logged into the site. We decided to use vueJS to fetch the data. Since we implemented 7 new API endpoints to get seven different data points, we made 7 parallel API requests. While waiting for a response, we only rendered 7 boxes with loading indicators. Whenever one of the data is returned through the API, the vueJS would update the graph and show it in the dashboard. Using this approach may have increased the number of network calls but we did not have to wait for the whole data to be fetched from the backend.

Since the empty dashboard was loaded at first, if the user wants to go to a different page they can go to that page from the navbar. These changes made the UI a little more responsive than before. Once that is done we moved to the next stage, which is using caching to serve data faster.

Implement caching to make response faster

Another strategy we have adopted to further improve the performance of the dashboard is to use Redis to cache the results. This means that the data is stored in Redis, which is a fast and lightweight database so that it can be retrieved quickly. Since Redis is in-memory data storage, it is able to store a large amount of data without consuming too much time, thus making it ideal for this purpose. Furthermore, since Redis is highly scalable, it is able to handle large volumes of data, making it an ideal solution for caching search results.

Redis is an open-source, in-memory data structure store that is used to cache data for faster retrieval. It helps to reduce the load time of search results by storing the result in memory, allowing users to access the data quickly. We decided to use Redis to cache the search results in order to improve the performance and reduce the time it took to query the database. Using Redis helped us to reduce the load on the database, saving time and resources.

In our case, the data in the dashboard did not have to be real-time updated. Instead, the requirement was like, as long as the data in the dashboard does not show any data that is more than 30 minutes old, they are ok with it. This made our work a little bit easier. We configured the redis in such a way so that the data expires within 30 minutes.

Here is an example code snippet using Node.js to set a value in Redis with an expiry of 30 minutes:

const redis = require('redis');
const client = redis.createClient();

client.set('myKey', 'myValue', 'EX', 1800, (err, reply) => {
  if (err) throw err;
  console.log(reply);
});

client.quit();

In this example, myKey is the key that we want to set in Redis and myValue is the value that we want to associate with the key. The third argument 'EX' indicates that we want to set an expiry time for the key, and the fourth argument 1800 sets the expiry time to 30 minutes (since the expiry time is measured in seconds).

The set method also takes a callback function that is executed when the operation is complete. If an error occurs, the error is thrown; otherwise, the reply from Redis is logged into the console.

Finally, we close the Redis client connection using client.quit().

So every time the frontend calls the APIs, we would check if the redis has any data about that, if there is we would just return that data otherwise, we would query the database and once we get the data, we would save the data in the redis with 30 min expiry and return that data as API response.

Conclusion

It’s not that hard to make the service faster, it was just a lot of rewrites. That is why I always tell people to think, is there a better way to complete a feature, before jumping into implementing a feature? Even if it may take more time right now to make it right, if we do not fix that, it will only consume more time to fix that later on.

Thank you for reading! What topic would you like me to write about next? Let me know and I’ll do my best to create a helpful blog post for you.

The Power of Refactoring: Transforming a Dashboard for Improved Load Time Read More »

Featured Image

Valid Parentheses | TypeScript Solution

In this post, I am going to talk about the Valid Parentheses problem, which you can find in Leetcode. For this problem I have used TypeScript to solve but you can use any language to solve this problem. It is fairly easy to solve. To solve this problem we need to use Stack. You can learn more about the stack data structure from here.

Full Solution for the Valid Parentheses problem

Valid Parenthesis problem solution

Check out my other solutions two sumValid Anagram and many more.

Valid Parentheses | TypeScript Solution Read More »

Feature image

Best Time to Buy and Sell Stock | Typescript Solution

In this post I am going to share how I solved the leetcode problem called Best Time To Buy and Sell Stock. Although this problem is marked as easy but if you do not understand how the sliding window works than it may seems a little bit tough.

What is Sliding Window

Let’s say you have an array or a list and your task is to find a suitable sub section of that array that satisfies a specific condition. For example, we can think that we have an array [1,2,3,4,5,6,7]. We need to find a subset (a portion of an array) where the addition of all the item is 7. In this scenario, let’s say the subset should contain only 2 items. Whenever we say a subset, most of the times it means those values should be together, side by side. That’s how I determine if I can solve a problem using Sliding window. You can take any two of them that are side by side and check if there sum is 7 or not. Here is a representation below for better understanding.

In here we follow this steps:

  1. Take index 0 and 1, Is there sum equals 7?
  2. If no, take index 1 and 2 and check again
  3. if no, take index 2 and 3 and check again,

We continue to do it until we reach the end of the array or whenever we the condition is satisfied

Ok got it. Now how can we solve the best time to buy and sell stock problem?

Now, In our case, we are supposed to do the same thing to solve this problem. We need to find out a sub array where the max amount of profit can be made. Or in other words, find a sub set of array elements that produces the highest number of value but adding them together.

So we at first set the left index as 0 and the right index as 1. We also assume that the max is 0. The left index is yesterday and the right index is today. Notice that we can not go to the previous day in stock price calculation. So whenever we see that the price of today is lower than whatever value we have in the left index, it means we are making a loss. If we are making a loss that we do not need to check any further. We point the left index value to the right index and start continuing from there again. And we continue to increase the window size. But if we see that we are making profit, we check if it the the max so far or not and store it based on that result.

Once we go through all the value we will have the max profit we can have. I have added a nice little animation to show how it works in action.

Animation of using sliding window to solve the problem

Full solution

Solution for Best time to buy and sell stock
Solution for the problem Best time to buy and sell stock

Check out my other solutions two sum, Valid Anagram and many more.

Best Time to Buy and Sell Stock | Typescript Solution Read More »

Feature image

Valid Palindrome – Leetcode | TypeScript Solution

In my previous post where I discussed about the two sum problem, I told that the solution for the Valid Palindrome and anagram are somewhat similar. However, the palindrome is much more easier than anagram. In this problem, we have to know if a phrase is a palindrome or not. For those who do not know what is Palindrome, “A phrase is a palindrome if  it reads the same forward and backward, after removing all the spaces and non-alphanumeric characters and it shouldn’t be case sensitive. “

From the definition, we can understand couple of things

  1. We have to transform the given text to either lowercase or uppercase
  2. We have to remove all the spaces
  3. We only need to get the words no extra non alpha characters


So we will first transformed all the characters to lowercase by using a lodash function called lowerCase. Once that is done, we will remove all the spaces by writing the below code

 const removedSpaces = lowerCase.split(' ').join('');

Once that is done now we have to remove all the extra non-alphanumeric characters. I was looking at the lodash library with does have a very good function called words. I really liked the functionality so I used that one. Now that I have removed all the clutter, all I have to do is to reverse the original string and check if the original and the reversed string are same. I have wrote the whole code in TypeScript and added it below.

Solution

Solution for the Valid Palindrome
Solution for the valid palindrome

Hello readers, If you are like me who wants to get better at coding, please check out my other blog posts where I solve other leetcode problems.

In the next post, I am going to solve 3Sum problem. You can also check out my other blog post as well.

Valid Palindrome – Leetcode | TypeScript Solution Read More »

Feature image

Two Sum – Leetcode Solution using JavaScript

Hello everyone. In this post, I am going to solve Two Sum problem from leetcode. This problem is related to arrays and hashing.

In this problem, given a target value, we have to find out the indices of the two numbers such that they add up to target. So for example if the array is [2,7,11,15] and the target is 9, then we have to return the index value [0,1]. Because the index value of 0 and 1 is 2 and 7. the addition of 2 and 7 is 9.

I solved the problem using JavaScript and I went with the straight forward way to solve it. It passed the submission! That’s why I did not think about any optimization or any other solution.

To solve this problem, I created a loop and inside that loop I created an inner loop. Basically checking every combination until I get a match. I do not think I need to explain any thing for this code. Please take a look at it and if you have any problem understanding please comment on the post. I will try my best to explain.

Solution

Two Sum Solution using JavaScript
Two Sum Solution

Hello readers, If you are like me who wants to get better at coding, please check out my other blog posts where I solve other leetcode problems.

In the next post, I am going to solve Valid palindrome. Although It is similar to Valid Anagram, if you face trouble check out my solution. There are a few slight changes in the condition.

If you like my solution, please check out my other post about various leetcode solutions. If you want me to solve any other leetcode problem, feel free to comment it below.

Two Sum – Leetcode Solution using JavaScript Read More »

Valid Anagram Feature Image

Valid Anagram Solution | Typescript | Leetcode problem

In this post, I am going to solve the Leetcode problem called Valid Anagram and provide solution using TypeScript. In this problem, given that we have 2 strings, we have to tell whether they are Anagram or not. For those who don’t know, An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

Though process for the valid anagram problem

Before trying to solve we can find a few clues about anagrams.

  1. As I stated earlier, both of the string will have same amount of letter.
  2. The number of letter occurrences will be same.

To solve a problem, I always check for the simple conditional part. That way, I can take out the obvious test cases which would fail. In this case, I need to check both of the strings are of same length. If not, then they are not anagram. Plain and simple. Which is why I wrote this line in the beginning of the code.

if(s.length !== t.length) return false;

For the second point, we need to check how many times a character/letter used. So I wrote a simple for loop that basically checks every character one by one and they it checks in it’s own dictionary to see if that was used before or not. If yes, I increase the value by one. If not, I add a new property in that dictionary. (Note: In JS/TS there is no direct way to use dictionary like python/C#, so we have to create an object and use it like a dictionary). Here is the code for that.

for(let i = 0; i<text.length; i++){
        const ch = text.charAt(i);

        if (ch in dict) {
            dict[ch] += 1;
        } else {
            dict[ch] = 1
        }
    }

I encapsulated the dictionary creation part into a nice little function so that it is easier to read the code. Once I am able to create the dictionary for both the original and the test string, I called a lodash function called isEqual. It performs a deep comparison between two objects. Here is the full code for the valid anagram solution.

Full Valid Anagram Solution

function isAnagram(s: string, t: string): boolean {
    if(s.length !== t.length) return false;
    
    const input = getDictionary(s);
    const testInput = getDictionary(t);
    
    return _.isEqual(input, testInput);
};

function getDictionary(text: string) {
    let dict: { [letter: string]: number } = {};
    
    for(let i = 0; i<text.length; i++){
        const ch = text.charAt(i);

        if (ch in dict) {
            dict[ch] += 1;
        } else {
            dict[ch] = 1
        }
    }
    
    return dict;
}

Hello readers, If you are like me who wants to get better at coding, please check out my other blog posts where I solve other leetcode problems.

In the next post, I am going to solve Two Sum problem. In the meantime, you can checkout the post I have written on another problem called Contains Duplicate

Valid Anagram Solution | Typescript | Leetcode problem Read More »

Contains Duplicate solution using JavaScript

Contains Duplicate | Leetcode problem

In this post, I would like to talk about one of the most easiest problem you can see in the leetcode. In this problem, we have to tell whether an array contains duplicate value or not. The link to this question is here. Note that, the given array is all integer. Below I will give a short explanation of the leetcode problem solution.

Thought process to solve the problem

Whenever, I face a situation where I have to find if there is any duplicate or not (we are not finding out which one is the duplicate one, just if there is any identical value or not), all I do is to check the length of the array at first. Then I convert the array to a set. Note that a set can not contain any repeating values. Once it is converted to a set, I just check if the length of the set is same as the array or not. if yes, then there is no duplicate, if no, that means there is some duplicated value.

I have added the the JavaScript version of my solution.

Full Contains Duplicate Solution

var containsDuplicate = function(nums) {
    const uniqueSet = new Set(nums);
    
    if(uniqueSet.size === nums.length) {
        return false;
    }
    return true;
};

Obviously there are a lot of ways to solve the “Contains duplicate” problem. Like maybe you can use a loop (like, for, while etc) to check if there is any repeating values. But it will not be efficient. As for this kind of problem we should focus on finding the best solution.

Thanks again. In the next post, I will talk about another leetcode problem solution called Valid Anagram using JavaScript. Stay tuned.

Contains Duplicate | Leetcode problem Read More »