DEV Community

Jaxongir
Jaxongir

Posted on • Edited on

How to Think like a Programmer

Introduction

In this blog post you learn to solve coding problems in a systematic way. And in fact that programming is in the core problem solving. So to be a great programmer then you have to be a problem solver and learn to think like a problem solver. One thing I see common among most if not all new or even some intermediate to advanced programmers is that when they face the problem in programming, they attack the problem at once and try to solve it by formulating algorithm in their head which is very wrong approach. And this process goes as following

  • 1. Try to solve the problem on head
  • 2. If you failed, you try again with different solution,
  • 3. If you agan failed (bash your head to the table or break the keyboard. I'm joking please don't do that :) ), try step 2 until your patience run out.

Problem with this appraoch is that you lose a lot of time and also your brain cells. But there's nothing wrong with not being able to have an optimal approach to solve the problem at the beginning. As this is mostly a beginner programmer problem, you'll eventually learn to solve the problem more like how a real programmer approaches to solve the problems. So in this blog post, I'm going to teach you how to correctly approach any coding problem and solve it in a systematic way. My goal is that once you read and understand concepts taught in this blog post is that you'll be equipped with the knoweldge so that you can solve the problem like a real programmer do. Remember even knowing how to solve problem in a systematic way, does not guarentee that you could solve any problem with ease, the more you solve coding problems by being patient, logical, perseverant, the better problem solver you become.

Key Terms You should Understand

  • Algorithm: Aglrotithm is the step by step appraoch solve the problem
  • Constraint: Constraint in coding is the rules which you must follow to solve the given problem
  • Refactor: Refactoring means editing code to improve code readability, it's speed, and it's memory consumption

6 Step by Step Approach to a Problem Solving

1. Understand the Problem

In step 1, you've to understand the problem by explaining the problem in your own words. Why you might ask? Well because when you understand the problem by reiterating it with your own words, you'll gain insights into the problem and solution comes easier.

If you can't explain something in simpler terms, it means is that you don't understand it - Richard Feynman

  • Include all the problem constraints In step 1, you will have to list all of the constraints of the current problem and solve problem according to these constraints

2. Recognize the similarity between current problem and previous solved problem

In step 2, you will find analogy between current and one of the solved problems. But this step is not for beginners so you can skip it if you are beginner, as being able to recognize similarities between current and already solved problems, you have to have solved hundreds of hundreds of problems.

  • Use previous similar solved problem to solve the whole or part of the current problem with the algorithm you implemented in the previous solved problem

3. Give Examples

In step 3, you'll give examples to the end result, to the solution which must meet constraints of the problem. In this way, you'll have visual example on what soluion should look like, which makes it easier to solve the problem.

4. Reduce the Problem

In step 4, you'll simplify the problem instead of attacking one big complex problem. You reduce the problem that you are unable to solve by either removing or adding constraints. You keep reducing the problem until you can no longer reduce the problem into simpler problem. It's like how compounds are made up of molecules and molecules are made up of atoms and attoms are irreducible unit.

5. Divide the Problem or Write Algorithm

Once you reduced the problem into irreducible problem, you start dividing or writing algorithm for the tiniest problem and you go up from there. You divide the problem and solve it and you connect all those dots(reduced problems) together starting from smallest to largest. Once all dots are connected, congratulations that you've solved the whole complex problem.

6. Refactor the solution

This step is very essential but most developers skip this step. As coder, you should have reflect and review mindset. Reflect on the aglorithm and review it and improve it. So in short in this step, you'll think about how you can make code cleaner/easier to read, reduce memory consumption of the algoritm, and make speed of the program faster. You'll look at other people' code that solved the same problem as the current problem you solved critically and implement code features they implemented which makes your code better.

Problem Solving Approach in Practise

So now, we've learned how to solve a problem like a programmer, now we are going to use it in practise.
PROBLEM: Write a program that prints the numbers from 1 to 100 and for multiples of ‘3’ print “Fizz” instead of the number and for the multiples of ‘5’ print “Buzz”. For numbers which are multiples of both 3 and 5, print "FizzBuzz" instead of the number.

1. Understand the Problem

Write a program that outputs numbers in the range of 1 to 100 inclusively to the console and program should output "Fizz" to the console if number is divisible by 3 and if number is not divisible by 5, program should output "Buzz" to the console. If number is divisible both by 3 and by 5, program should output "FizzBuzz".
- Constraints:
- Program can only output Fizz, Buzz, FizzBuzz,
- Numbers are ranged from 1 to 100 inclusively

2. Look for Similarities between Current and Previously Solved Problem

We can skip this part, but in the future when you will solve problems try to think similaraties between current and previous solved problem

3. Give Examples to the Solution

printFizzBuzz(6) =>
1
2
Fizz
4
Buzz
6

4. Reduce the Problem

Problem simplicity is oredered from simplest to hardest(original)
1. Reduced Version: we reduce the problem where we only have to print numbers from 1 to 100
2. Reduced Version: In this step have to print only Fizz or Buzz and numbers
3. Reduced Version: Last step where have to print both Fizz, Buzz, FizzBuzz and numbers

5. Divide the Problem

1. Algorithm for 1st Reduced Version of the Problem:

    1. create a function that takes single parameter
    2. check if given input is number and in the range of 1-100, if not return error
    3. create loop that loop through 1 to 100 inclusively and in each iteration do following
        1. print each number 1-100 inclusively
Enter fullscreen mode Exit fullscreen mode
const printFizzBuzz = (num) => {
  if (typeof num !== "number" || (num < 0 && num > 100)) {
    return "Please provide only number which should be in range of 1-100 inclusively";
  }
  for (let i = 1; i <= num; i++) {
    console.log(i);
  }
};

Enter fullscreen mode Exit fullscreen mode

2. Algorithm for 2nd Reduced Version of the Problem. As we have already created function and loop, we have to figure out to print Fizz and Buzz

    1. In each iteration inside the loop do following
        1. If number is divisible by 3 which returns no remainder then print Fizz
        2. If number is divisible by 5 which returns no remainder then print Buzz
        3. else print number
Enter fullscreen mode Exit fullscreen mode
const printFizzBuzz = (num) => {
  if (typeof num !== "number" || (num < 0 && num > 100)) {
    return "Please provide only number which should be in range of 1-100 inclusively";
  }
  for (let i = 1; i <= num; i++) {
    if (i % 3 === 0) {
      console.log("Fizz");
    } else if (i % 5 === 0) {
      console.log("Buzz");
    } else {
      console.log(i);
    }
  }
};

Enter fullscreen mode Exit fullscreen mode

3. Algorithm for 3rd Reduced Version of the Problem. So last step is figuring out how to print FizzBuzz. Basically number that's multiply of 3 and 5, should

    1. In each iteration inside the loop do following
        1. If number is divisible by multiply of both 3 and 5 together then it should print FizzBuzz
        2. If number is divisible by only 3 which returns no remainder then print Fizz
        3. If number is divisible by only 5 which returns no remainder then print Buzz
        4. else print number
Enter fullscreen mode Exit fullscreen mode
const printFizzBuzz = (num)=>{
            if(typeof num !== 'number' || num < 0 && num > 100){
                return "Please provide only number which should be in range of 1-100 inclusively"
            }
            for(let i = 1; i <= num; i++){
                if(i % 15 === 0){
                    console.log("FizzBuzz");
                } else if(i % 3 === 0){
                    console.log("Fizz");
                } else if(i % 5 === 0){
                    console.log("Buzz");
                } else {
                    console.log(i);
                }
            }
        }
Enter fullscreen mode Exit fullscreen mode

6. Refactor

We can take validating to it's function to make printFizzBuzz more functional and to follow Single Responsibility Rule

const isValidNumber = (num) => {
  return typeof num !== "number" || num < 0 || num > 100 ? false : true;
};
const printFizzBuzz = (num) => {
  if (!isValidNumber(num)) {
    return "Please provide only number which should be in range of 1-100 inclusively";
  }
  for (let i = 1; i <= num; i++) {
    if (i % 15 === 0) {
      console.log("FizzBuzz");
    } else if (i % 3 === 0) {
      console.log("Fizz");
    } else if (i % 5 === 0) {
      console.log("Buzz");
    } else {
      console.log(i);
    }
  }
};

Enter fullscreen mode Exit fullscreen mode

SUMMARY
So in this post, you've learned how to think like a programmer and appraoching problems in a systematic way. And we applied it in pracitse. This skill gets better as all other skills by doin a lot of PRACTICE PRACTISE and PRACTICE. If you liked and learned something in this blog post, please leave your feedbacks or share it with your friends so that they can also benefit.

Top comments (0)