Think like a programmer.
General Problem-solving techniques to aid you problem-solving and logical thinking
I got into tech at the beginning of summer, 2020. Before then, I had no idea what direction I wanted to face in life but one thing was for sure, I have always aimed higher every time it seemed like I failed. Here, I had gotten over 200 rejection mails for customer service jobs ( Can you believe that ? ๐ ). I got my first job but quickly realized something was missing! For a long time I couldn't figure out what it was that I was lacking, but it affected me badly, no matter how much I tried.
One year and five months after, I finally figured it out; My problem solving skills. I loved solving problems but I couldn't figure out how to solve the problems. I had a weak math background but I was determined to change this. Once I moved into software development at the end of fall, 2021, I knew right there and then it was for me. There was so much challenges and my brain was getting a constant supply of dopamine and with every new challenge I was able to solve, I got more and more of it.
I was solving my problems, but it looked to me like I wasn't solving my problems logically enough. I didn't just want to be a programmer who is able to just do a given task. I wanted to be much more. I wanted to be a problem solver, a logical thinker. I wanted to breathe in programming and breathe out results, and not just through google searches, and guess works. I wanted more! But, for something who has a "not so good" mathematical and logical thinking background, I needed to find my way and this led me to a series of good investments. One of which I'm about to share tips from.
Problem-solving
According to google, problem solving is the act of defining a problem; determining the cause of the problem; identifying, prioritizing, and selecting alternatives for a solution and implementing the solution.
Imagine this;
You have a car, and while traveling a long distance, you realize there is a smoke coming out of your tailpipe and it has lost fuel efficiency. This is a problem that can be easily solved with an automotive knowledge, diagnosis, replacement equipment and common shop tools. You call your friend and she says to you "Why not just trade your car for a new one and problem is solved" . Your friend's suggestion would solve the problem but that isn't a solution to this problem, it's just a way to avoid the problem.
Problems include constraints, unbreakable rules about the problem or the way in which the problem must be solved. With the broken down car, one of the constraints is that you want to fix the car, not purchase a new one. The constraint here might also include the overall cost of repair and the time it will take to repair this.
In programming, we face constraints as well when solving problems, some of which could be programming language, platform ( if it runs on a PC, an iPhone, or what), performance etc.
Fortunately, problems faced by programmers can be solved although lots of programmers still resort a non-effective approach, sometimes accidentally such as " Oh! My solution only works with this, but I'm supposed to have that. Maybe I can just stick to this since it works ๐" ( I still find my self doing this a few times, but I am being intentional about it, so when I catch myself doing this, I quickly snap out of it).
Sometimes it's because we don't know how to meet this constraints- at least for me- but the more attempts you make, the better you get at it.
General problem-solving techniques
Here are a few methods to attack your problems:
Always have a plan
Personally, I tend to jump right into things without thinking it through and this way when I'm faced with a constraint that seems impossible, i am quick to go on google searching a broad question, hoping to find an answer already spelt out. But it is really important to have a plan for how you will solve the solution. Naturally, I'm very spontaneous but General Dwight D. Eisenhover would always say;
I have always found that plans are useless, but planning is indispensable.
He meant that battles are so chaotic that it is impossible to predict everything that could happen and have a predetermined response for every outcome. In that sense, plans are useless on the battlefield but no army can succeed without planning and organization. Through planning, a general learns what his army's capabilities are, how different parts of the army works together and so on.
In the same way, we must always have a plan for solving a problem. Planning also allows you set immediate goals and achieve them. Without a plan, you have only one goal, which is to solve the whole problem and until you have solved the problem, you won't feel like you have achieved anything. Working towards only a primary goal, leads towards frustration as there are no positive reinforcements from your efforts until the end. If you instead, create a series of minor goals, you will always make measurable progress towards a goal and feel like your time has been spent usefully.
- Restate the problem
Restating a problem is like circling the base of a hill that you must climb; before starting to climb, why not check out the hill from every angle to see whether there's an easier way up? Restating a problem can show the goal was not what we thought it was. With a plan already created, you can make "Formally restate the problem" your first step. Even if this doesn't lead to an immediate insight, it can help you understand better and in other cases, if you were assigned a problem, restating can help you confirm your understanding of the task at hand.
Divide the problem
Finding ways to divide the problem into smaller steps or phases can make the problem a lot more easier. Dividing a problem can often lower the difficulty by an order of magnitude. Some problems hide their potential sub division but finding ways to find a problem's divisions can reduce the problem.
Start with what you know
When I start playing sudoku, I try to spot the parts that I can solve easily first. Mostly parts that have most numbers already. I am able to quickly figure out what numbers go in the remaining empty boxes and doing this, reveals some answers to parts that are more difficult. A articular problem may be entirely solvable with the knowledge and skills you already have or it may not. But you should investigate the problem using the skills already in your head before looking elsewhere.
- Reduce the problem
When faced with a problem you are unable to solve, you should try reducing the scope of the problem, by either adding or removing constraints , to produce a problem that you do know how to solve. Reduction simplify problems in many ways. Reducing the problem allows you to pin-point exactly where the remaining difficulties lies.
- Look for analogies
In my case, I realized sometimes, I had previously learnt a particular thing and now I need it to solve a different problem, but unfortunately, it's lost in a big chunk of code somewhere. I even tried to search the source where I learnt it from, but it's gone. So, I started documenting things learnt, and in that way, I don't have to start from scratch again, I can easily exploit a problem I already solved to help solve the current problem. Although recognizing analogies is the most important way to improve your speed and skill at problem solving, it is also the most difficult skill to develop. The reason it is difficult is because you can't look for analogies until you have a storehouse of previous solutions to reference. Writing you code is very necessary to understand your code, so if you go online to look for a similar code to what you need, copy it and modify it, you won't have fully understood and internalized it. Every successful program you write, is more than a solution to a current problem; it's a potential source of analogies to solve future problems.
- Experiment
Sometimes, the best way to make progress is to try things and observe the results. Experimentation is different from guessing. Refrain from guessing as you have zero belief and only just hope your code works. An experiment is a controlled process. You hypothesize what will happen when certain code is executed, try it out and see whether your hypothesis is correct. This way you are able to gain information that will help you solve the original problem.
Experimenting may be especially helpful when dealing with application programming interfaces or class libraries. Consider creating a short program to play around with a vector class that you've never worked with before for example; Suppose you are writing a program that uses a library class representing a vector (in this context, a one-dimensional array that automatically grows as more items are added), but you've never used this vector class before, and you're not sure what happens when an item is deleted from the vector. Instead of forging ahead with solving the original problem while uncertainties swirl inside your head, you could create a short, separate program just to play around with the vector class and to specifically try out the situations that concern you. If you spend a little time on the "vector demonstrator" program, it might become a reference for future work with the class.
Other forms of experimentation are similar to debugging. Suppose a certain program is producing output that is backward from expectations for example, if the output is numerical, the numbers are as expected, but in the reverse order. If you don't see why this is occurring after reviewing your code, as an experiment, you might try modifying the code to deliberately make the output backward (run a loop in the reverse direction, perhaps). The resulting change, or lack of change, in the output may reveal the problem in your original source code or may reveal a gap in your understanding. Either way, you're closer to a solution.
- Don't get frustrated
When you are frustrated, you are unable to think clearly and you won't be as efficient as you should which means everything will take longer and seem harder. When you allow yourself to get frustrated, you give yourself an excuse to fail. If you are working on a difficult problem and you feel frustrated, take a break from it. When you have a plan and you realize writing the code that solves the original problem is the goal of the plan, it is not the only step of that plan. Thus, if you have a plan and you are following it, then you are making real progress. And if you have run all the steps on the original plan, and you are still not ready to start coding, then it's time to make another plan.
When it comes to getting frustrated, always take a break. The trick here is to have more than one problem to work on, so if one has you worked up or stuck, yo can turn your efforts elsewhere.
Conclusion
To truly learn something, you have to practice. I not only follow these steps, I continue to develop my logical thinking skills by playing games that stimulate that part of my brain and taking logical thinking tests. Try out some exercises. Work on puzzles that requires logical reasoning and planning. Learning never stops and I will continue to update as I learn more about solving problems and thinking like a developer.
I hope you learned something new and will implement it in your day to day life at least. ๐