megacolorboy

Abdush Shakoor's Weblog

Writings, experiments & ideas.

Say Hello, New Blog

Everything from new updates to shifting to a static site generator.

Hello, 2019!

Uhh, I guess it's a bit too late, but better late than never!

Lately, the concept of using a static site generator has become the new rage. This blog that you are seeing now is powered by a custom-built static site generator written on Python and trust me, I love it!

Why shift from a dynamic to static website?

It took me some time to make a decision on why I would need to make a shift from a dynamic website to a website that serves static files, here are some of my reasons:

  • Edit posts using Markdown
  • Increased speed
  • Eliminates the use of CMS and Databases
  • Pre-generated and will be served on request without any delay
  • Lightweight
  • Ease of Maintenance
  • More secure

Apart from that, I wanted to understand the concept of Static Site Generators, so I thought of writing a static site generator using Python.

Sure, there are many static site generators available online but I always like to be the curious cat!

How it works

Nothing complicated, the concept is pretty simple. All you have to do is write down your articles in Markdown and when you execute your static site generator, it will compile all your posts from your directory into individual static files using a template, which can then be served to your visitors.

For example, let's say you have a markdown file named hello-world.md and you wrote your content:

title: Hello World
date: 2019-03-01 20:00

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ut sollicitudin dui, 
pulvinar vulputate nibh. Cras eu nunc mauris. Vestibulum quis diam at diam feugiat semper vitae at sem. 
Mauris in orci iaculis mauris semper gravida at nec augue. Phasellus luctus accumsan velit, 
in molestie odio luctus at. Curabitur neque erat, pretium vitae condimentum placerat, sodales eu 
nisi. Cras pretium nulla ac est interdum, vitae tempor mauris ornare. 
Nullam tortor nisi, scelerisque vel purus id, dictum finibus erat. Nulla tincidunt egestas 
sodales. Sed sit amet elit placerat, pellentesque est in, bibendum enim. Nam dolor lorem, venenatis sit 
amet sem at, sagittis feugiat risus. Fusce turpis felis, sodales a tortor vitae, volutpat semper 
justo. Donec porta id mi non porttitor. Fusce id est sit amet leo consectetur consequat.

Also, this is your template:

<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
    <div>Published on: {{ date }}</div>
    {{ content }}
    </body>
</html>

And when you execute the application, this is what happens:

<html>
    <head>
        <title>Hello World</title>
    </head>
    <body>
    <div>Published on: 2019-03-01 20:00</div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ut sollicitudin dui, 
    pulvinar vulputate nibh. Cras eu nunc mauris. Vestibulum quis diam at diam feugiat semper vitae at sem. 
    Mauris in orci iaculis mauris semper gravida at nec augue. Phasellus luctus accumsan velit, 
    in molestie odio luctus at. Curabitur neque erat, pretium vitae condimentum placerat, sodales eu 
    nisi. Cras pretium nulla ac est interdum, vitae tempor mauris ornare. 
    Nullam tortor nisi, scelerisque vel purus id, dictum finibus erat. Nulla tincidunt egestas 
    sodales. Sed sit amet elit placerat, pellentesque est in, bibendum enim. Nam dolor lorem, venenatis sit 
    amet sem at, sagittis feugiat risus. Fusce turpis felis, sodales a tortor vitae, volutpat semper 
    justo. Donec porta id mi non porttitor. Fusce id est sit amet leo consectetur consequat.
    </body>
</html>

The generator just parsed your article on Markdown and put the details on the template and tada, the article is generated. Easy peasy!

The next step is to deploy it, I wrote a bash script to deploy all static files via FTP onto my server.

It's a simple but powerful idea and gives me a lot of flexibility to create my future blog posts with each having a different look (not always, but sometimes).

Refreshed look, Creative energy

Although, the old one was good and minimal, something felt empty about it and I decided to change it.

I experimented with different fonts and chose Fira Sans as the blog's primary font. As for colors, I took inspiration from Dropbox's recent change in branding and they combined various colors to create dynamic elements to their brand.

So, I wrote a pattern generator on Javascript that would create a background image for every blog post and make it look colorful (See above).

“Floating Lines in the DeepSpace”. A generative artwork by Miguel Neto & Rodrigo Carvalho.

Also, I have been exploring the concept of Generative Art, I found it really interesting especially it's creative and mathematical aspect. I have plans on replacing these colorful patterns with the random generative artworks, after all, I don't aim to make it look boring.

Discovery and Experimentation

I have been working on some side projects like Pac-Man clone, a text-editor based on C and a terminal-based to-do list application on Linux, learning and customizing VIM, tinkering with Vagrant boxes, Capture-The-Flags challenges, experiments with UI frameworks like ReactJS and so much more.

Hang in there, it's not over!

It's a work-in-progress and I'm trying to make my blog to be more creative, interactive and colorful.

I will be hosting a separate section called "Projects", which is currently under the works, it will contain all of my projects, UI/UX components to play around with, games and much more. I hope it will be the coolest section of this blog.

Hope you liked reading this article and the new changes!

Peace Out!

Goodbye, Windows 10!

An essay on why I switched from Windows 10 to Ubuntu 18.04 LTS.

Ah, it's been a long time since I had posted anything on my blog. In today's article, I will be talking about my switch from Windows 10 to Ubuntu 18.04 LTS.

Why did I make the switch?

I grew up using different versions of Windows OS and my favorite one is Windows 7. I use Windows 8.1 at work and macOS High Sierra on my mid-2010 MacBook Pro at home.

Recently, I bought myself a Dell XPS 9360 for serious development. Below are the specs:

  • Intel Core i7 @ 2.4Ghz 7th Generation
  • 256GB SSD
  • 8GB RAM
  • 13.3" Inch Full-HD Display

However, I did have an issue with it, it came pre-installed with a bloated Windows 10.

I tried giving Windows 10 a shot even after reading several blog posts on how Microsoft collects data, forces updates that users can't opt out of and so on.

Then one fine day, I left my laptop to download some files and then Windows decides to update without asking for my permission. My download got disrupted and I finally decided to make the switch.

Besides that, I wanted to have a good environment that's secure, programmer friendly and wanted to use the Terminal, which is a programmer's sweet spot for automation, executing scripts and accessing remote machines and so on.

Choosing a Linux distribution

At first, I wanted to try out Arch Linux for it's strong community and amazing configurations but I thought of taking a safe side by trying out Ubuntu.

I downloaded the latest distribution from the official website and created a bootable USB drive. Later, I changed my laptop's BIOS configuration to Legacy mode from it's UEFI Secure Boot mode, which was a bit annoying.

After everything was done, I plugged in the bootable USB drive and voila, Ubuntu's loaded on my screen.

Check for Hardware Compatibility

If you've read some articles, you might find some people writing out comments that when you install Linux on your computer, you might face some hardware compatibility issues. You can be detect it beforehand by trying it out on a bootable USB drive.

Luckily, thanks to Dell's hardware support for Linux, it detected all of my laptop's hardware without any issues.

I decided to go with a minimal installation as I don't want to have any bloatware on my computer.

Hello Ubuntu!

Ubuntu's new user interface looks really clean and minimal and it looked really vibrant in my laptop's Full HD Display.

The boot time was fast and it took a mere few seconds to display the login screen. As soon as I logged in, I installed the necessary development tools such as gcc, python, perl, git, node.js, npm package manager, Emacs text editor and more.

Conclusion

Well, every operating system has it's own pros and cons, likewise, Linux has a few cons such as that I won't be able to use Adobe applications like Photoshop and Illustrator but that's not a big deal for me as my focus is purely on development.

If you're a programmer and serious about development, I would strongly recommend you to try it out and you'll never want to return back to Windows again.

Hope you liked reading this article!

Adios Amigo!

Artificial Intelligence: A Modern Approach - Chapter 1

An introduction into the foundations of Artificial Intelligence.

It's something that I had in my mind for a long time but never got the time to execute it but finally, I decided to get out of my comfort zone to learn new concepts and techniques that would enable me to solve new problems. Hence, I chose to study Artificial Intelligence.

Artificial Intelligence, A Modern Approach (3rd Edition)

I did some online research and found out a really good book named Artificial Intelligence, A Modern Approach (3rd Edition) by the Stuart Russell and one of my favorite computer scientists, Peter Norvig (Director of Research at Google) to learn about it's concepts and techniques. The book has 1000+ pages and it's a book used for undergraduate and graduate level courses in university.

My current knowledge of Artificial Intelligence is pretty basic (e.g: write game AI) and I want to learn more about it and be able absorb any information related to it and build toy AI projects.

I've completed the first chapter of the book, so let's dive in because this going to be a long read.

What is Artificial Intelligence?

We read about it in the news, it's being deployed in our mobile applications that we use everyday such as Facebook, Instagram, Twitter, Reddit and so on to filter out graphic content, fake information and insensitive political content. It's also being used in games such as chess, scientific research, diagnosis of several diseases and self-driving cars.

But do we know what is it? According to Google Search, it means:

The theory and development of computer systems able to perform tasks normally requiring human intelligence such as visual perception, speech recognition, decision-making and translation between languages. 

It encompasses a huge number of fields and sub-fields and AI is already the next big thing that it's shaping our everyday life.

Approaches towards AI

The book states that there are four types of approaches when it comes to creating an AI:

Four approaches towards AI.

Acting Humanly

Proposed by British computer scientist Alan Turing, the Turing Test approach was designed to provide a functional definition of Artificial Intelligence. The test is proved positive only when a human is unable to tell the difference between the results of a computer or a human. In order to think like a human, it should possess the following capabilities:

  • Natural Language Processing to enable communication in any language with the human
  • Knowledge Representation to store what it knows or hears
  • Automated Reasoning to make conclusions based on the repository of information to answer questions
  • Machine Learning to learn and adapt to new patterns and extrapolations

It is to be noted that the test deliberately avoided interaction with the human because physical interaction with the human wasn't necessary for intelligence.

Then came another test called Total Turing Test, this was made to test the computer's ability of visual perception. The computer passes this test when it's possess the following abilities:

  • Computer Vision to be able to perceive and identify objects
  • Robotics to be able to manipulate physical objects
Sony's AIBO Home Entertainment robot.

The abilities mentioned above, composes most of what modern AI is today and Turing deserves a huge credit for designing this test that still remains relevant for more than 60+ years.

Thinking Humanly

Do we know how humans think? Maybe, but for us to be able to determine that, we would need to achieve a deep understanding of the human mind works. There are a few ways such as:

  • Introspection by catching our own thoughts as they pass by
  • Psychological experiments by observing the actions or behavior of a human
  • Brain imaging by observing the brain in action
Fields that contributed to the birth of cognitive science.

Once we have sufficient information, it's possible to theorize that a computer program behaves like a human. Cognitive Science enables you to combine both computational models of an AI and psychological experimentation techniques to provide testable theories as to how the human mind works.

Thinking Rationally

Greek Philosopher Aristotle attempted to arrange information based on irrefutable evidence based on the process of reasoning. His rules of inference a.k.a syllogisms (a form of reasoning in which conclusions are drawn from various propositions or a set of premises) provided patterns that yielded correct conclusions from correct premises. For example: "Socrates is a man; All men are mortal; therefore, Socrates is a mortal being". These laws of thought initiated the study of logic, which gave hope to 19th century logicians to help create intelligent systems.

Marble bust of Greek Philosopher Aristotle.

However, there are two main obstacles to this logical approach. Firstly, it's difficult to convert informal information into formal terms required by logical notations especially when the information isn't 100% certain. Secondly, being able to solve a problem in theory vs. solving a problem in practice are two different things. You can have a computer that can solve a problem with a few hundred facts yet use up all of it's resources.

Acting Rationally

This is focused on creating intelligent agents that can perform various tasks like being able to operate autonomously, perceive objects, adapt to change, create new goals and pursue them. A rational agent is an agent that acts to achieve the best expected outcome.

Making the right conclusions based on evidences i.e. correct inferences is part of a rational agent because to act rationally, an agent must be able to reason with logic to reach to a conclusion for a given action to achieve one's goals.

However, it doesn't necessarily that it's always "correct", sometimes, it has there's no such thing as the "right" thing to do but something must be done.

A simple agent reflex.

The skills needed for a Turing Test allows an agent to act rationally especially on making good decisions using Knowledge Representation and Automated Reasoning, generating intelligible sentences using Natural Language Processing for a complex society, adapting to change and generating effective behavior using Machine Learning.

But, there are some advantages to this approach. Firstly, it's more general in terms of the logical approach (mentioned in Thinking Rationally). Secondly, it's more open to scientific development compared to human behavior (mentioned in Acting Humanly) and human thought (mentioned in Thinking Humanly). The standard rationality of an agent is purely mathematically defined and completely general whereas human behavior adapts to a specific environment.

Later, the book states that it's focus is going to be based on the general principles of rational agents and on components for constructing them.

Is AI a science, or is it engineering?

As I was reading the book, it was fascinating to see how various disciplines have contributed ideas, techniques and viewpoints to the field of Artificial Intelligence. The following disciplines are:

  • Philosophy
  • Neuroscience
  • Mathematics
  • Economics
  • Linguistics
  • Psychology
  • Computer engineering
  • Control theory and cybernetics

Each disciplines had thoughtful questions like How does a human brain work? How are valid conclusions drawn from formal rules? How can we build an efficient computer? How to think and communicate in one's language? How does the brain process large amounts of information? How do humans and other living things think and act? How does language relate to thought?

This part of the book is really long but it was a good way to understand about it's early foundations.

How is it useful today?

Well, that's not very easy to answer because it's being used in multiple fields and sub-fields. There are so many applications such as:

  • Self Driving Cars
  • Speech Recognition
  • Facial Recognition
  • Fighting Malware and Spam bots
  • Filtering graphic content and fake information from social media
  • Game playing AIs for different board games like Checkers, Go and Chess
Chinese Government surveillance system using Facial Recognition.

All of this used to be science fiction but thanks to the advancements of Mathematics, Science and Engineering, it's become a reality in today's era.

Conclusion

Well, I don't know if this is one of the longest articles I have ever written but I really did enjoy writing this because this made me read the chapter again and gained a better understanding of the concepts.

I will be writing more articles about it, write algorithms and build toy  implementations of Artificial Intelligence applications.

In fact, I wrote this article to answer all, if not, most of the questions from the exercises section of this chapter.

Hope you liked reading this article!

Stay tuned for more!

Extras

Built a 2048 clone in 15 minutes

An implementation of the famous 2048 game using JavaScript and HTML5 Canvas.

Before you read more about this article, play with the above game. You can move the tiles around using your or WASD keys. The rule is simple, when two tiles with the same number touch, they merge into one tile. Press the R key to restart the game.

Please make sure that you have JavaScript enabled and running in your browser, otherwise you won't be able to play this game. Oh, just a little heads up, it might get a little buggy and freeze your browser window, so keep calm and play patiently.

As for the source code, you can view it in my GitHub repository or can be found near the end of this article.

Background

I was always fond of puzzle games and 2048 is one of them. The first time I got to play this game was back in 2014 and I would play it on my iPhone during my train commute to university.

Yesterday, I thought of building a clone and turns out it wasn't as hard as I had expected it to be, in fact, I was able to build a functional version in just 15 minutes.

What are the game mechanics?

The sliding-puzzle game is played on a four-by-four grid with numbered tiles that is moved by the player in all four directions.

In every move, a new tile would randomly appear in an empty spot in the grid with a value that consists of 2 or 4. These tiles are moved towards any direction as far as it could and if there are two tiles that collide with the same value, they merge into one tile and as a result, the score is updated.

The player wins the game once the tile of 2048 appears on the grid, thus is the name of the game.

Source code

var canvas = document.getElementById("game-grid");
var ctx = canvas.getContext("2d");
var size = 4;
var cell_width = canvas.width / size - 6;
var grid = [];
var font_size;
var is_lose = false;
var score = 0;
function cell(row, col) {
this.value = 0;
this.x = col * cell_width + 5 * (col + 1);
this.y = row * cell_width + 5 * (row + 1);
}
function create_grid() {
for (var i = 0; i < size; i++) {
grid[i] = [];
for (var j = 0; j < size; j++) {
grid[i][j] = new cell(i, j);
}
}
}
function draw_cell(cell) {
ctx.beginPath();
ctx.rect(cell.x, cell.y, cell_width, cell_width);
var fillColor = "";
switch (cell.value) {
case 0:
fillColor = "#eee";
break;
case 2:
fillColor = "#b8e994";
break;
case 4:
fillColor = "#78e08f";
break;
case 8:
fillColor = "#38ada9";
break;
case 16:
fillColor = "#079992";
break;
case 32:
fillColor = "#82ccdd";
break;
case 64:
fillColor = "#60a3bc";
break;
case 128:
fillColor = "#3c6382";
break;
case 256:
fillColor = "#0a3d62";
break;
case 512:
fillColor = "#6a89cc";
break;
case 1024:
fillColor = "#4a69bd";
break;
case 2048:
fillColor = "#1e3799";
break;
default:
fillColor = "#eee";
break;
}
ctx.fillStyle = fillColor;
ctx.fill();
//If it's not an empty cell i.e. anything greater than 0
if (cell.value) {
font_size = cell_width / 2;
ctx.font = font_size + "px sans-serif";
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.strokeStyle = 'rgba(0,0,0,0.075)';
ctx.stroke();
ctx.fillText(cell.value, cell.x + cell_width / 2, cell.y + cell_width / 2 + cell_width / 7);
}
}
function draw_grid() {
for (var i = 0; i < size; i++) {
for (var j = 0; j < size; j++) {
draw_cell(grid[i][j]);
}
}
}
//Check for free cells
function empty_cells_lookup() {
var count = 0;
for (var i = 0; i < size; i++) {
for (var j = 0; j < size; j++) {
if (!grid[i][j].value) {
count++;
}
}
}
return count;
}
//Check if 2048 is reached
function check_2048() {
for (var i = 0; i < size; i++) {
for (var j = 0; j < size; j++) {
if (grid[i][j].value == 2048) {
return true;
}
}
}
return false;
}
function newCell() {
var num_empty_cells = empty_cells_lookup();
//If the grid is full, then game is over
if (!num_empty_cells) {
game_status("game-over");
return;
}
if (check_2048()) {
game_status("game-win");
return;
}
while (true) {
var row = Math.floor(Math.random() * size);
var col = Math.floor(Math.random() * size);
if (!grid[row][col].value) {
grid[row][col].value = 2 * Math.ceil(Math.random() * 2);
draw_grid();
return;
}
}
}
function game_status(status) {
var message = "";
switch (status) {
case "game-over":
message = "Looks like it's Game Over!";
break;
case "game-win":
message = "Congratulations, you won the game!";
break;
}
ctx.font = "25px sans-serif";
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText("Your score: " + score, 250, 250);
ctx.font = "15px sans-serif";
ctx.fillStyle = "black";
ctx.textAlign = "center";
ctx.fillText(message, 250, 300);
ctx.fillText("Press 'R' to play again.", 250, 320);
canvas.style.backgroundColor = "#eee";
is_lose = true;
}
function move_up() {
var row;
for (var j = 0; j < size; j++) {
for (var i = 1; i < size; i++) {
//If it's a number greater than zero
if (grid[i][j].value) {
row = i;
while (row > 0) {
//Case 1: Move the number to an empty cell
if (!grid[row - 1][j].value) {
//The current cell's value is assigned to the cell above
grid[row - 1][j].value = grid[row][j].value;
//The current cell is empty
grid[row][j].value = 0;
//By decrementing, it's moving up the grid
row--;
} else if (grid[row - 1][j].value == grid[row][j].value) {
grid[row - 1][j].value *= 2;
score += grid[row - 1][j].value;
grid[row][j].value = 0;
break;
} else {
break;
}
}
}
}
}
}
function move_down() {
var row;
for (var j = 0; j < size; j++) {
for (var i = size - 2; i >= 0; i--) {
//If it's a number greater than zero
if (grid[i][j].value) {
row = i;
while (row + 1 < size) {
//Case 1: Move the number to an empty cell
if (!grid[row + 1][j].value) {
//The current cell's value is assigned to the cell above
grid[row + 1][j].value = grid[row][j].value;
//The current cell is empty
grid[row][j].value = 0;
//By decrementing, it's moving up the grid
row++;
} else if (grid[row + 1][j].value == grid[row][j].value) {
grid[row + 1][j].value *= 2;
score += grid[row + 1][j].value;
grid[row][j].value = 0;
break;
} else {
break;
}
}
}
}
}
}
function move_left() {
var col;
for (var i = 0; i < size; i++) {
for (var j = 1; j < size; j++) {
//If it's a number greater than zero
if (grid[i][j].value) {
col = j;
while (col > 0) {
//Case 1: Move the number to an empty cell
if (!grid[i][col - 1].value) {
//The current cell's value is assigned to the cell above
grid[i][col - 1].value = grid[i][col].value;
//The current cell is empty
grid[i][col].value = 0;
//By decrementing, it's moving up the grid
col--;
} else if (grid[i][col - 1].value == grid[i][col].value) {
grid[i][col - 1].value *= 2;
score += grid[i][col - 1].value;
grid[i][col].value = 0;
break;
} else {
break;
}
}
}
}
}
}
function move_right() {
var col;
for (var i = 0; i < size; i++) {
for (var j = size - 2; j >= 0; j--) {
//If it's a number greater than zero
if (grid[i][j].value) {
col = j;
while (col + 1 < size) {
//Case 1: Move the number to an empty cell
if (!grid[i][col + 1].value) {
//The current cell's value is assigned to the cell above
grid[i][col + 1].value = grid[i][col].value;
//The current cell is empty
grid[i][col].value = 0;
//By decrementing, it's moving up the grid
col++;
} else if (grid[i][col + 1].value == grid[i][col].value) {
grid[i][col + 1].value *= 2;
score += grid[i][col + 1].value;
grid[i][col].value = 0;
break;
} else {
break;
}
}
}
}
}
}
function init() {
create_grid();
draw_grid();
newCell();
newCell();
}
function canvasClean() {
ctx.clearRect(0, 0, 500, 500);
}
init();
//Events
document.onkeydown = function(e) {
if (e.keyCode == 82) {
canvas.style.backgroundColor = "white";
is_lose = false;
score = 0;
canvasClean();
// updateScore();
init();
}
//If the game is still on
if (!is_lose) {
switch (e.keyCode) {
//Move Up
case 38:
case 87:
move_up();
updateGame();
break;
//Move Down
case 40:
case 83:
move_down();
updateGame();
break;
//Move Left
case 37:
case 65:
move_left();
updateGame();
break;
//Move Right
case 39:
case 68:
move_right();
updateGame();
break;
}
}
}
function updateGame() {
//Clear the grid
canvasClean();
//Generate another random number after movement is complete
newCell();
}
view raw 2048.js hosted with ❤ by GitHub

Well then, that's all for the game. Just like the previous ones, I had fun building this sliding-puzzle game. I'm looking forward to building more puzzle games and talking about them in my blog.

Hope you guys liked reading this article and have fun playing the game as many times as you like!

Stay tuned for more!

Can we eliminate traffic congestion with the help of Computer Vision?

Writing out my thoughts on eradicating traffic congestion in highly populated cities.

Whether it's being implemented or not, I have been thinking on how we could use Computer Vision to solve traffic congestion.

Since, I live in the United Arab Emirates, I have always observed that people who commute from Sharjah to Dubai and vice-versa face a lot of traffic jams despite all the new roads and toll-gates (yes, I don't seem to understand how does that solve the problem).

Traffic in Al Ittihad Highway.

Well, the problem is not only faced in this country but many countries such as China, Indonesia and so on.

What are the causes of traffic congestion?

Anyways, I jotted down some facts to consider what causes traffic congestion in the first place:

  • Tail-gating
  • Inconsistent travel speeds
  • Uneven vehicular distances
  • Spontaneous accidents and road rages
  • Changing from one lane to another
  • Increase in car population
  • Peak hours i.e. people going to work and leaving from work

I'm sure that there could be more but these are the facts that I can come up with for now.

How can Computer Vision solve this problem?

Computer Vision is a field that intersects with multiple areas of technologies in which it aims to develop an understanding of objects by extracting information from various digital media sources like images and videos and automate those tasks that a normal human would do in their daily lives.

Visualization of Computer Vision.

There are various types of problems that Computer Vision algorithms are able to solve but not limited to:

  • Object Recognition or Object Classification
  • Identification of Objects
  • Object Detection
  • Analysis of Motion

Now, it's not only about implementing these CNN-based (Convolutional Neural Network) algorithms but you also need hardware to be able to compute and process data. 

How would this work?

There are two scenarios that I had thought while writing this article and I hope that I'm able to translate my thoughts into accurate examples.

Let's pretend we have four car drivers: Alex, Bob, Charlie and Dylan.

Speed-Distance equilibrium

Alex, Bob and Charlie are driving on the same lane. Alex hits the brake slowly to shift to another lane, the sensors of Bob's car detects a change in speed in Alex's car, Bob's car adjusts it's speed to match Alex's current speed based on the variables of distance and travel time, Charlie's car adapts the changes of Bob's car and thus, it's a chain reaction.

Shifting from one lane to another

Alex is driving in Lane A and Dylan is driving in Lane B. Alex wants to shift to Lane B, so he switches on the indicator and Dylan's car sensors identify that Alex's car wants to change lanes. So Dylan's car slows down and Alex is able to shift lanes with ease. I thought of it to be some sort of a "elastic" effect when this occurs.

Well, you might argue that some cars have a system called "Cruise Control" but here's the part that I'm trying to pitch, as I had mentioned above, I just wanted to integrate sensors to the front and rear sides of a vehicle, which means that these sensors can be integrated in almost any vehicle.

How is this going to be helpful?

For starters, traffic congestion will gradually reduce, if not, be eliminated but there are other beneficial factors to it, such as:

  • Less fuel consumption
  • Less time is required to reach a destination
  • No tail-gating
  • Could prevent major road accidents

However, if the sensors fail to work, the car driver will still be safe because it's surrounded by other cars that have the sensors. This made me think of another question, does that mean do all cars require sensors or only a few? I find it quite intriguing.

Conclusion

Although, these sensors might require a vehicle to have some intelligent capabilities, it may not require the type of network found in an autonomous vehicle.

The idea of placing sensors in the front and rear of a vehicle can optimize the flow of traffic and thus, it might help eliminate traffic congestion.

Hope you liked reading this article!

Meet Blog Engine 2.0

Basically, a minimal blog engine with a paper-like user interface with better enhancements.

Blog engine updated!

As of March 1st 2019, I have changed my blog engine from a dynamic website to a custom-built static site generator. Read more →

Whenever I'm writing a new blog post, I would write it using HTML on my text editor i.e. using Sublime Text and copy-paste the source code into my blog engine and hit "Submit" and that was really annoying.

You might be thinking to yourself as to why I'm putting myself through such a tedious process to write a blog article when there are several WYSIWYG text editor plugins.

Truth is, I have to admit that I was lazy and I cared a lot about writing my blog articles but never cared about the tool I had built that to write my blog articles, so I decided to upgrade it and make it even better than what it was previously!

Why rewrite it?

For starters, the old one had a clunky and pretty much boring user interface. I used CKEditor text editor plugin but to be honest, I rarely used any of it's features as I was just directly copy-pasting my source code from Sublime Text to the text field box.

Over time, it became slow due to spaghetti code and it required a lot of code refactoring as I wrote this code during my earlier days of programming by following various programming tutorials.

Here's some screenshots of the old blog engine:

Fig.1: Index Page
Fig.2: List of blog posts
Fig.3: Edit page

And, last but not the least, it didn't make me feel like I was writing a blog but rather felt like writing HTML code in a more tedious manner.

Time for a change!

For the past two weeks, I have been working on a new version of the blog engine and I had decided to give it some new features like:

  • Clean and paper-like user interface by taking inspiration from Google's Material Theming Design guidelines
  • Minimal text editor built from scratch that can be extensible in the future
  • Auto-save article every minute
  • Emojis, LaTeX syntax, JavaScript files and IFRAME windows
  • Live search bar to filter articles by keywords or categories

In case, you're wondering, I built this using vanilla JavaScript and a custom-built MVC PHP framework with a MySQL database.

Here's some screenshots of the new blog engine:

Fig.4: Index page with a better UI
Fig.5: Minimal Text Editor

What I really wanted to achieve with the new blog engine is that I want to give myself an enjoyable writing experience besides, this blog post was written from the new blog engine.

Well, it's stable as of yet but I need to run a few tests and build more functionalities before deploying it on my production server and finally saying good-bye to the old version.

Hope you liked reading this article!

Build and Design software with Empathy

Can seeing things from another's perspective create empathy and help solve technical challenges?

Recently, I've started reading this book named Designing For Emotion by Aarron Walter and I've made it a point to read it during my free time and so far I have completed three chapters of the book.

In the first chapter of the book, I found a really interesting sentence, written by the author:

Keep in mind that ignoring human needs is not a history we are doomed to repeat. Through our designs, we can see and connect with other human beings.

Do you think a good software builds strong connections with other human beings? Well, we have good examples like Facebook, Google, Netflix, and Microsoft are proof that they have a massive pool of audience who likes to use their products on a daily basis.

In this article, I will share some of my thoughts on how empathy can be used to build and design powerful applications.

User Interface Matters

To any user, whatever is displayed on the application matters the most, in this case, it's the User Interface of an application. If it doesn't allow a user to perform their desired task, it will end up in their Recycle Bin.

Fig. 1: Apple's Ping

There are many examples in the book and one of the examples is about Apple's Ping (refer to Fig. 1), which was an attempt in creating a social network on iTunes but it turned out to be unsuccessful as users learned that they weren't able to share songs on Facebook or Twitter and it lacked basic features. As a result, users didn't come back to it again.

In my opinion, a good user interface should be relatively easy to use and be more reliable in terms of pagespeed or simple and easy navigation for the user. I mean, think about it, if your user is able to complete their desired task and that puts a smile on their face, the user will share their experiences to their friends and you'll get more people to use your application, thus making your application more powerful.

A Universal Design

A door knob comes with multiple designs such as rotating knobs and levers but what matters the most to the people? The design or the functionality? I personally prefer a lever knob over a rotating knob as I find it quite annoying. Weird analogy but the point is, it should just open the door, nothing fancy.

Similarly, when we build our software, by following proper techniques, we can choose to make it beautiful but also choose to make it accessible and functional for everybody, at all costs.

Listen to your users

When building and designing a piece of code, it should and always be for the people that uses or will use your product. By understanding what's important to the users, it can help you get to the core of the problem and surpass technical challenges easily.

This can be achieved by gathering user requirements in the form of surveys, user feedback and A/B testing. Remember, software is just an expressive form of bringing your ideas to life and writing code is building on top of the idea to achieve a certain goal but empathy is the secret sauce to the success of your application.

UX is not UI

What's the first thing that comes to your mind when a friend of yours tells you: "Hey, I'm working as a UX Designer at UberCoolCorp!"? Does he build User Interfaces? Is he a Visual Graphics Designer? Neither, actually!

User Experience is not about how your application looks but how it feels and makes it simple and easier to interact with your users. I'd like to share an interesting quote from Usabilla's UX Expert, Erik Flowers:

UX is the intangible design of a strategy that brings us to a solution.

User Experience encompasses a lot of elements such as Information Architecture, Interaction Design, Usability, Product Design and so on. Below is a picture for your reference about why User Experience is not User Interface:

Fig. 2: How UX wants to be seen.

Although, it does have a lot of elements, UI is a huge part of the design process because strong visual aesthetics are still essential in UX, which is also one of the aspects of your user's interactions with the application.

Progressive Enhancement

A strategy that is known to take you on journey from simplicity to complexity. It's about starting off with a strong, practical foundation and then building on top of it. It's easier to maintain and make small yet incremental changes, renders the application to be more robust and it works for all users.

Conclusion

Well, I'm sure there a lot of elements to this topic but I thought of highlighting some of the most important parts of building and designing software with empathy. As engineers or developers, it is our job to ensure that our final product is usable and accessible to our end-user.

Hope you liked reading this article!

Stay tuned for more!

Extras

Lexicographic Permutations

How to generate the next permutation of any given sequence in lexicographical order.

According to Problem 24 in Project Euler, you are asked to find the millionth permutation using the following sequence of 10 digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9). Well, if you do the math, there are around 10! = 3,628,800 unique permutations and that means, you have to come up with an efficient algorithm.

I tried writing a recursive function but it turned out to be a bit tricky, so I thought of writing a brute-force solution which seemed far more simpler to understand and it's quite efficient.

Algorithm Description

The following algorithm is quite simple and easy to understand:

1. Find i such that a[i-1] is greater than or equal to a[i].
2. Find j such that a[j-1] is less than or equal to a[i-1].
3. Swap a[i] with a[j].
4. Reverse the suffix from a[i+1] to the last element.

Suppose, if the first step fails, it means the current permutation is the last one because such an index that does not exist. However, it's simple to implement the following algorithm correctly and efficiently, so let's take a look at the implementation.

Python Implementation

The following method only generates the next permutation of any given sequence, so if you're interested in generating all the permutations, especially, for very large lists, this function can be useful.

Implementation of the method(s):

# Swap numbers in a list
def swap(list, i, j):
    list[i], list[j] = list[j], list[i]

# Get the next permutation
def nextPermutation(list):

    i = len(list) - 1

    # As long as the f(x-1) >= f(x), decrement the first index
    while list[i-1] >= list[i]:
        i = i-1

    j = len(list)

    # As long as the f(y-1) <= f(x-1), decrement the second index
    while list[j-1] <= list[i-1]:
        j = j-1

    # make a swap
    swap(list, i-1, j-1)

    i = i+1
    j = len(list)

    # keep swapping until you get the next permutation
    while i < j:
        swap(list, i-1, j-1)
        i = i+1
        j = j-1

    return list

Final code:

#!usr/bin/python
import math, time, pe_lib

start = time.time()

list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

count = 1
limit = 1000000

while count < limit:
    pe_lib.nextPermutation(list)
    count = count + 1

print "".join(str(x) for x in list)
print "Finished: %f seconds" % (time.time() - start)

This code in executed in approximately 2.37 seconds with an algorithmic complexity of O(n) i.e. linear time complexity and the replacements of the numbers were done in-place since no extra space was used.

Hope you liked reading this article!

References