Cracking the Code: Unveiling the secret of Problem-Solving.
Published: 2023-05-18 13:57:30


Cracking the Code: Unveiling the secret of Problem-Solving.

Yesterday was the dumbest I'd ever felt in a while. I couldn't solve a programming problem; I couldn't think through it to find a solution. I work by the principle of staying with problems longer to be able to solve them, but yesterday I almost ditched that principle. I sought a break and went in search of books that would entertain me and keep me away from anything like programming for 2 weeks.

Last night, I was thinking about this intensely and sobbing at how stupid I had become because I could barely solve a programming problem. And in a split moment, I let my mind wander to what I planned to adopt as a small distraction: reading books. In that split moment, I received an epiphany. I figured out the pattern that all programming problems share, and I will break down this pattern into 3 rules.

First, find the output—what is expected of you from the problem—then define it immediately. Make it a variable and store it in the data structure you were asked to use (yeah, it's usually subtly specified).

Second, find what you have—the input. Determine what you have been given. You may have been given a data structure as well.

Now, use the rules that govern what you have and what you are asked to return. There's usually a common factor, or even multiple common factors. Understanding these rules will help you craft a perfect algorithm.

I followed this pattern and tackled 4 problems in a row. The problems ranged from easiest to medium difficulty. And this morning, I have started again. Lol. Despite this newfound power, I still need a holiday—not to help me figure things out, but as a form of reward for myself for not breaking my principle.

In reference to the previous paragraphs, consider a problem where you are asked to find the maximum number given a list of numbers. It's not specified whether you're given all integers or not, so make sure your solution takes care of all edge cases.

To give you a better idea, here's the problem:

**_"Write a Python function called find_max that takes a list of numbers as input and returns the maximum number in that list. For example, if the input is [5, 2, 9, 1, 7], the function should return 9."_**

Now let's put my rules into play.

First rule: Identify what you have been asked to return.

In the problem above, we have been asked to return a single number from a list of numbers. The max could be at the first index, the second, or even the nth index. Since we aren't sure, let's store the return value, which is a single item from the list, in a variable like so:

`max_num = num_list[0]`

We are picking the first index because we aren't sure of which index the maximum value might be. Hence, it's safer to start from the first index since it affords us the chance to go through the other numbers from there.

Second rule: Consider what you have been given... the input.

In the above problem, the input is a list of numbers. This is going to help us with our third rule.

Third rule: Find the common rule that exists between what you are trying to find and what you have been given.

In our case, the common rule guiding the list that you have been given and the single integer you are asked to return is that both are numbers, and finding the maximum is not going to involve too much other than comparing values that you have selected and what you currently have.

So the algorithm in here is to basically pick one number at a time, check whether the number you are currently holding is bigger than what you stored earlier. If it is, then let max_num be the number you found.

You do this for all numbers since there are chances that you could pick the next number, compare it, and find it is even bigger than the one you held before. Then you have to replace it. And when you have gone through all the numbers and have managed to find the maximum, return it. Let's see the code in full:


```
def find_max(list_num):
    max_num = list_num[0]
    for num in list_num:
        if num > max_num:
            max_num = num
    return max_num
```
So there it is, how to think through a problem. Of course, there are other elegant solutions, and there's also a function in Python that helps you check the maximum value, but writing a solution from scratch and without already defined functions tests your understanding and really helps you gain confidence in problem-solving.

Expanding on the illustration above, let's explore two more problems that can be solved using the same pattern.

**Problem 1: Counting the Occurrence of an Element in a List**

Suppose you are given a list of integers, and you need to write a function that counts the number of times a specific element occurs in the list. Let's call this function count_occurrence. For example, given the list [1, 2, 3, 2, 4, 2, 5], if we want to count the occurrence of the number 2, the function should return 3.

Using the problem-solving pattern mentioned earlier, let's break it down:

First rule: Identify what you have been asked to return.
In this case, we need to return a single value, which is the count of the occurrence of the element. So, let's initialize a variable count to 0 to keep track of the count.

Second rule: Consider what you have been given... the input.
The input is a list of integers.

Third rule: Find the common rule that exists between what you are trying to find and what you have been given.
The common rule here is that both involve integers. We need to iterate through the list and compare each element with the given element to count its occurrence.

Using this information, we can write the count_occurrence function as follows:


```
def count_occurrence(lst, element):
    count = 0
    for num in lst:
        if num == element:
            count += 1
    return count
```

**Problem 2: Reversing a String**

Let's consider another problem where we need to write a function to reverse a given string. The function, reverse_string, should take a string as input and return the reversed string. For example, if the input is "Hello, World!", the function should return "!dlroW ,olleH".

Applying the problem-solving pattern:

First rule: Identify what you have been asked to return.
In this case, we need to return a string, which is the reversed version of the input string.

Second rule: Consider what you have been given... the input.
The input is a string.

Third rule: Find the common rule that exists between what you are trying to find and what you have been given.
The common rule here is that both involve strings. We need to iterate through the input string and construct the reversed string by adding each character in reverse order.

Based on this, we can implement the reverse_string function:


```
def reverse_string(input_str):
    reversed_str = ""
    for char in input_str:
        reversed_str = char + reversed_str
    return reversed_str
```
In conclusion, the problem solving pattern discussed in the initial illustration provides a systematic approach to tackling programming problems. By breaking down the problem into three rules—identifying the expected output, considering the given input, and finding the common rule between them—it becomes easier to devise an effective algorithm.

The first rule emphasizes the importance of clearly understanding the desired output of the problem. By defining it immediately and storing it appropriately, it sets a clear goal for the solution. In the example of finding the maximum number in a list, the variable max_num was used to store the initial assumption and later updated as necessary.

The second rule prompts us to analyze the given input, including its data structure. This understanding enables us to formulate a solution that operates based on the characteristics of the input. In the case of finding the maximum number, the input was a list of numbers, which guided the iteration and comparison process.

The third rule focuses on identifying the common rule that links the desired output and the given input. Recognizing this commonality helps establish the core logic of the algorithm. In the case of finding the maximum number, the common rule was the comparison of numbers, allowing the algorithm to iterate through the list, compare each number, and update the max_num variable accordingly.

Expanding on the original illustration, we explored two additional problems that follow the same problem-solving pattern. The first problem involved counting the occurrence of a specific element in a list, while the second problem revolved around reversing a string.

In the case of counting occurrences, the three rules were applied to determine the desired output, consider the given input, and identify the common rule of comparing integers. The resulting solution involved iterating through the list, comparing each element to the specified element, and incrementing a count variable accordingly.

For the string reversal problem, the rules guided the identification of the desired output (reversed string), understanding the given input (the original string), and recognizing the common rule of manipulating strings. The solution involved iterating through the characters of the input string and constructing the reversed string by adding each character in reverse order.

By employing the problem-solving pattern and following the three rules, programmers can approach a wide range of problems with a systematic mindset. This approach promotes clarity, reduces complexity, and improves the chances of finding efficient solutions. While the examples provided demonstrate how the pattern can be used, it is essential to adapt and modify the approach based on the specific requirements and constraints of each problem.

Ultimately, embracing problem-solving techniques and persisting through challenges are key factors in overcoming obstacles and enhancing one's problem-solving skills. With practice and experience, programmers can further refine their problem-solving abilities and become more confident in their problem-solving journeys.