# Unit-4: Introduction to problem solving Concept : BCA semester 1

Problem solving is a critical skill in computer science and programming. It refers to the process of finding solutions to problems or challenges by applying logic and critical thinking.

Here are some key concepts in problem solving:

- Understanding the problem: This involves carefully reading and comprehending the problem statement and defining the problem in your own words.
- Analyzing the problem: This involves breaking down the problem into smaller, more manageable parts and identifying the information and data required to solve the problem.
- Formulating a plan: This involves creating a step-by-step plan for solving the problem, including the methods and algorithms that will be used.
- Implementing the plan: This involves coding the solution and testing it to ensure that it works as expected.
- Evaluating the solution: This involves analyzing the solution to ensure that it’s correct, efficient, and meets the requirements of the problem.
It’s important to note that problem solving is an iterative process and may require multiple iterations of the above steps. The goal is to find a solution that works and meets the requirements of the problem. Effective problem solving skills require patience, persistence, and a willingness to try different approaches until the right solution is found

- those sub-problems in a table for later reuse. For example, you can use dynamic programming to solve a problem by breaking down a large data set into smaller chunks and storing the solutions to each chunk in a table for later reuse.
- Recursion: This involves breaking down a problem into smaller sub-problems and solving each sub-problem recursively. For example, you can use recursion to solve a problem by breaking down a large data set into smaller chunks and solving each chunk recursively until you have the final solution.
It’s important to note that different problems may require different problem solving techniques, and that a single problem may have multiple solutions using different techniques. Effective problem solving skills require being able to identify the right technique for the problem at hand and using it to find the optimal solution.

## trial & error

Trial and error is a problem solving technique in programming where you test various solutions to a problem and evaluate their results to determine the best solution. This technique involves trying out different solutions and evaluating their results until you find the correct solution.

Here’s an example of trial and error in programming:

Suppose you have to write a program to find the square root of a number. You can start by trying out different solutions using the trial and error technique. For example, you can try dividing the number by 2, then by 3, then by 4, and so on, until you find a number that, when multiplied by itself, is close to the original number. You can then use this number as an approximation of the square root.

With trial and error, you can iteratively test different solutions until you find the correct one. This technique is often used when there is no clear or known solution to a problem. It’s important to note that trial and error can be time-consuming and may not always produce the most efficient solution, but it can still be an effective technique for finding a solution to a complex problem

## brainstorming

Brainstorming is a problem solving technique in programming where a group of people generate a large number of ideas or solutions to a problem. This technique involves generating as many ideas as possible in a short period of time without evaluating them. The goal is to generate a large number of ideas that can later be evaluated and refined.

Here’s an example of brainstorming in programming:

Suppose you have to write a program to manage a library’s inventory. You and your team decide to use brainstorming to generate as many ideas as possible for the program’s features. During the brainstorming session, you and your team generate a large number of ideas, such as:

- A search function to find books by author, title, or ISBN
- A check-in/check-out function to keep track of which books are checked out
- A notification system to remind users when a book they have checked out is due
- A rating system to allow users to rate books they have read
- A recommendation system to suggest books to users based on their reading history

After the brainstorming session, you and your team evaluate the ideas generated and refine them to come up with the final solution for the program. Brainstorming can be an effective technique for generating a large number of ideas and can be especially useful in a team setting where multiple perspectives can be brought to bear on a problem

### Divide and Conquer

Divide and Conquer is a problem solving technique that involves breaking down a complex problem into smaller, more manageable sub-problems, and then solving each sub-problem individually. This technique is often used to solve problems that are too complex to be solved in one step, or to find solutions to problems where a brute force approach is too time-consuming or infeasible.

Here’s an example of divide and conquer in programming:

Suppose you have to sort a large array of numbers. One way to sort the array is to use a divide and conquer approach by dividing the array into smaller sub-arrays, sorting each sub-array individually, and then merging the sorted sub-arrays back together to form the final sorted array.

The divide and conquer approach can be implemented using a sorting algorithm such as merge sort, where the array is recursively divided into smaller sub-arrays until each sub-array contains only one element, at which point the sub-arrays are merged back together in sorted order. This approach can be more efficient than a brute force approach, as it allows you to solve the problem in smaller, more manageable steps.

Divide and conquer can be a useful technique for solving complex problems, as it allows you to break down the problem into smaller, more manageable sub-problems that can be solved individually. By solving each sub-problem separately, you can find solutions to the larger problem that would otherwise be difficult or impossible to find

## Steps in problem solving

- Define the problem: Clearly identify and understand the problem that needs to be solved.
- Gather information: Collect data and information related to the problem.
- Develop potential solutions: Generate multiple possible solutions to the problem.
- Evaluate potential solutions: Assess each solution based on its potential effectiveness, feasibility, and impact.
- Select a solution: Choose the best solution based on the evaluation.
- Implement the solution: Put the chosen solution into action.
- Monitor progress: Continuously monitor and evaluate the solution to ensure it is solving the problem effectively.
- Refine the solution: Make necessary adjustments to the solution if it is not working as intended.

## Algorithms and Flowcharts

The **algorithm and flowchart** are two types of tools to explain the process of a program. In this page, we discuss the differences between an algorithm and a flowchart and how to create a flowchart to illustrate the algorithm visually. **Algorithms and flowcharts** are two different tools that are helpful for creating new programs, especially in computer programming. An algorithm is a step-by-step analysis of the process, while a flowchart explains the steps of a program in a graphical way.

### Definition of Algorithm

Writing a logical step-by-step method to solve the problem is called the **algorithm**. In other words, an algorithm is a procedure for solving problems. In order to solve a mathematical or computer problem, this is the first step in the process.

An algorithm includes calculations, reasoning, and data processing. Algorithms can be presented by natural languages, pseudocode, and flowcharts, etc.

### Definition of Flowchart

A flowchart is the graphical or pictorial representation of an algorithm with the help of different symbols, shapes, and arrows to demonstrate a process or a program. With algorithms, we can easily understand a program. The main purpose of using a flowchart is to analyze different methods. Several standard symbols are applied in a flowchart:

Common Abbreviations Used in P&ID

Terminal Box – Start / End | Image |

Input / Output | Image |

Process / Instruction | Image |

Decision | Image |

Connector / Arrow | Image |

The symbols above represent different parts of a flowchart. The process in a flowchart can be expressed through boxes and arrows with different sizes and colors. In a flowchart, we can easily highlight certain elements and the relationships between each part.

#### Difference between Algorithm and Flowchart

If you compare a flowchart to a movie, then an algorithm is the story of that movie. In other words, **an algorithm is the core of a flowchart**. Actually, in the field of computer programming, there are many differences between algorithm and flowchart regarding various aspects, such as the accuracy, the way they display, and the way people feel about them. Below is a table illustrating the differences between them in detail.Algorithm

ALGORITHM

- It is a procedure for solving problems.
- The process is shown in step-by-step instruction.
- It is complex and difficult to understand.
- It is convenient to debug errors.
- The solution is showcased in natural language.
- It is somewhat easier to solve complex problem.
- It costs more time to create an algorithm.

Flowchart

- It is a graphic representation of a process.
- The process is shown in block-by-block information diagram.
- It is intuitive and easy to understand.
- It is hard to debug errors.
- The solution is showcased in pictorial format.
- It is hard to solve complex problem.
- It costs less time to create a flowchart.

## types of algorithm

### #1 Recursive Algorithm

It refers to a way to solve problems by repeatedly breaking down the problem into sub-problems of the same kind. The classic example of using a recursive algorithm to solve problems is the Tower of Hanoi.

### #2 Divide and Conquer Algorithm

Traditionally, the divide and conquer algorithm consists of two parts: 1. breaking down a problem into some smaller independent sub-problems of the same type; 2. finding the final solution of the original issues after solving these more minor problems separately. The key points of the divide and conquer algorithm are:

- If you can find the repeated sub-problems and the loop substructure of the original problem, you may quickly turn the original problem into a small, simple issue.
- Try to break down the whole solution into various steps (different steps need different solutions) to make the process easier.
- Are sub-problems easy to solve? If not, the original problem may cost lots of time.

### #3 Dynamic Programming Algorithm

Developed by Richard Bellman in the 1950s, the dynamic programming algorithm is generally used for optimization problems. In this type of algorithm, past results are collected for future use. Like the divide and conquer algorithm, a dynamic programming algorithm simplifies a complex problem by breaking it down into some simple sub-problems. However, the most significant difference between them is that the latter requires overlapping sub-problems, while the former doesn’t need to.

### #4 Greedy Algorithm

This is another way of solving optimization problems – greedy algorithm. It refers to always finding the best solution in every step instead of considering the overall optimality. That is to say, what he has done is just at a local optimum. Due to the limitations of the greedy algorithm, it has to be noted that the key to choosing a greedy algorithm is whether to consider any consequences in the future.

### #5 Brute Force Algorithm

The brute force algorithm is a simple and straightforward solution to the problem, generally based on the description of the problem and the definition of the concept involved. You can also use “just do it!” to describe the strategy of brute force. In short, a brute force algorithm is considered as one of the simplest algorithms, which iterates all possibilities and ends up with a satisfactory solution.

### #6 Backtracking Algorithm

Based on a depth-first recursive search, the backtracking algorithm focusing on finding the solution to the problem during the enumeration-like searching process. When it cannot satisfy the condition, it will return “backtracking” and tries another path. It is suitable for solving large and complicated problems, which gains the reputation of the “general solution method”. One of the most famous backtracking algorithm example it the eight queens puzzle.

## Use Flowcharts to Represent Algorithms

### #1 Recursive Algorithm

It refers to a way to solve problems by repeatedly breaking down the problem into sub-problems of the same kind. The classic example of using a recursive algorithm to solve problems is the Tower of Hanoi.

### #2 Divide and Conquer Algorithm

Traditionally, the divide and conquer algorithm consists of two parts: 1. breaking down a problem into some smaller independent sub-problems of the same type; 2. finding the final solution of the original issues after solving these more minor problems separately. The key points of the divide and conquer algorithm are:

- If you can find the repeated sub-problems and the loop substructure of the original problem, you may quickly turn the original problem into a small, simple issue.
- Try to break down the whole solution into various steps (different steps need different solutions) to make the process easier.
- Are sub-problems easy to solve? If not, the original problem may cost lots of time.

### #3 Dynamic Programming Algorithm

Developed by Richard Bellman in the 1950s, the dynamic programming algorithm is generally used for optimization problems. In this type of algorithm, past results are collected for future use. Like the divide and conquer algorithm, a dynamic programming algorithm simplifies a complex problem by breaking it down into some simple sub-problems. However, the most significant difference between them is that the latter requires overlapping sub-problems, while the former doesn’t need to.

### #4 Greedy Algorithm

This is another way of solving optimization problems – greedy algorithm. It refers to always finding the best solution in every step instead of considering the overall optimality. That is to say, what he has done is just at a local optimum. Due to the limitations of the greedy algorithm, it has to be noted that the key to choosing a greedy algorithm is whether to consider any consequences in the future.

### #5 Brute Force Algorithm

The brute force algorithm is a simple and straightforward solution to the problem, generally based on the description of the problem and the definition of the concept involved. You can also use “just do it!” to describe the strategy of brute force. In short, a brute force algorithm is considered as one of the simplest algorithms, which iterates all possibilities and ends up with a satisfactory solution.

### #6 Backtracking Algorithm

Based on a depth-first recursive search, the backtracking algorithm focusing on finding the solution to the problem during the enumeration-like searching process. When it cannot satisfy the condition, it will return “backtracking” and tries another path. It is suitable for solving large and complicated problems, which gains the reputation of the “general solution method”. One of the most famous backtracking algorithm example it the eight queens puzzle.

## Use Flowcharts to Represent Algorithms

### Example 1: Print 1 to 20:

**Algorithm:**

- Step 1: Initialize X as 0,
- Step 2: Increment X by 1,
- Step 3: Print X,
- Step 4: If X is less than 20 then go back to step 2.

Image

### Example 2: Convert Temperature from Fahrenheit (℉) to Celsius (℃)

**Algorithm:**

- Step 1: Read temperature in Fahrenheit,
- Step 2: Calculate temperature with formula C=5/9*(F-32),
- Step 3: Print C.

Image

### Example 2: Convert Temperature from Fahrenheit (℉) to Celsius (℃)

**Algorithm:**

- Step 1: Read temperature in Fahrenheit,
- Step 2: Calculate temperature with formula C=5/9*(F-32),
- Step 3: Print C.

## Characteristics of an algorithm

- Input: An algorithm must have zero or more inputs that define the problem to be solved or the data to be processed. The input can be in the form of values, variables, or any other data structures.
- Output: An algorithm must have a well-defined output, which can be a single value, multiple values, or a set of values. The output must be related to the problem that the algorithm is trying to solve.
- Definiteness: An algorithm must have a well-defined set of steps or instructions that are executed in a specific order. These steps must be clear and unambiguous.
- Finiteness: The algorithm must terminate after a finite number of steps. It must not run indefinitely or get stuck in an infinite loop.
- Feasibility: An algorithm must be implementable, meaning that it can be translated into a program that can be executed on a computer.
- Effectiveness: The algorithm must be efficient and solve the problem in a reasonable amount of time and with a reasonable amount of resources, such as memory and computational power.
- Generality: The algorithm must be able to solve a wide range of problems or process a wide range of data, not just specific cases.
- Optimality: An algorithm can be optimal if it produces the best possible solution for a given problem, or if it produces the solution in the minimum amount of time or with the minimum amount of resources.

if (x > 0)

then print “x is positive”

else if (x < 0)

then print “x is negative”

else

then print “x is zero”

In this example, if the condition “x > 0” is true, the code inside the first “if” statement will be executed. If the condition “x > 0” is false, the program will move on to the next condition, “x < 0”. If this condition is true, the code inside the second “if” statement will be executed. If both conditions are false, the code inside the “else” statement will be executed.

These are the basic concepts of conditionals in pseudo-code. The use of conditionals is essential in programming for controlling the flow of a program and making decisions based on the input data.

## loops in pseudo code

Loops are a powerful programming construct that allow the repetition of a set of instructions multiple times, until a certain condition is met. In pseudo-code, loops are typically expressed using the keywords “for” or “while”.

A “for” loop is used to repeat a set of instructions a specific number of times. The basic syntax of a “for” loop in pseudo-code is as follows:

for i = 1 to n

do (action to be repeated n times)

For example, consider a program that prints the first 10 positive integers:

for i = 1 to 10

do print i

In this example, the “for” loop will repeat the instruction “print i” 10 times, and each time the value of “i” will be incremented by 1.

A “while” loop is used to repeat a set of instructions as long as a certain condition is true. The basic syntax of a “while” loop in pseudo-code is as follows:

while (condition)

do (action to be repeated while condition is true)

For example, consider a program that prints the positive integers until a certain number is reached:

input max

i = 1

while (i <= max)

do

print i

i = i + 1

In this example, the “while” loop will repeat the instructions “print i” and “i = i + 1” as long as the condition “i <= max” is true. The loop will terminate when “i” is no longer less than or equal to “max”.

These are the basic concepts of loops in pseudo-code. The use of loops is essential in programming for repeating actions, processing large amounts of data, and automating tasks.

## Time complexity

Time complexity is a measure of the amount of time an algorithm takes to complete, as a function of the size of the input data. It provides a way to compare the performance of different algorithms and to evaluate the efficiency of a particular algorithm.

The time complexity of an algorithm is typically expressed using big O notation, which provides an upper bound on the number of operations performed by the algorithm as a function of the size of the input. For example, an algorithm with a time complexity of O(n) is said to have a linear time complexity, meaning that the number of operations performed is proportional to the size of the input data.

A common example of a linear time complexity algorithm is a linear search. In a linear search, an algorithm checks each element in an array one by one until it finds the target element. The time complexity of this algorithm is O(n), because the number of operations required to find the target element increases linearly with the size of the array.

Another example is a binary search, which is an algorithm for finding an element in a sorted array. The time complexity of binary search is O(log n), because the number of operations required to find the target element decreases logarithmically with the size of the array. This makes binary search a much faster algorithm than linear search for large arrays.

In summary, time complexity is a critical aspect of algorithm design and analysis. Understanding the time complexity of an algorithm is important for evaluating its performance, comparing it to other algorithms, and optimizing its efficienc

## Big-Oh notation

Big-Oh notation, also known as big O notation, is a mathematical notation used to describe the upper bound on the growth rate of the time complexity of an algorithm. It provides a way to compare the performance of different algorithms and to evaluate the efficiency of a particular algorithm.

Big-Oh notation is expressed as O(f(n)), where “f(n)” is a function of the size of the input data. For example, an algorithm with a time complexity of O(n) is said to have a linear time complexity, meaning that the number of operations performed by the algorithm is proportional to the size of the input data.

Big-Oh notation only provides an upper bound on the growth rate of the time complexity, and does not provide an exact measure of the running time of an algorithm. For example, an algorithm with a time complexity of O(n) may take 100 operations for an input of size 100, but only 10 operations for an input of size 10. The big O notation only indicates that the number of operations will not grow faster than linearly with the size of the input.

Big-Oh notation is a useful tool for comparing the performance of different algorithms and for evaluating the efficiency of a particular algorithm. Some common time complexities expressed using big O notation include O(1) for constant time, O(log n) for logarithmic time, O(n) for linear time, O(n log n) for log-linear time, and O(n^2) for quadratic time.

In summary, big O notation is a mathematical notation used to describe the upper bound on the growth rate of the time complexity of an algorithm. It provides a way to compare the performance of different algorithms and to evaluate the efficiency of a particular algorithm

### Algorithms and flowcharts (Real Life Examples)

Algorithms and flowcharts are tools that are commonly used in a variety of real-life situations to represent and solve problems in a structured and efficient manner. Here are a few examples of how algorithms and flowcharts are used in real life:

- Cooking recipes: Cooking recipes are often written as algorithms, with each step represented in a clear and sequential manner. For example, a recipe for making cookies might include steps such as: preheat oven, mix ingredients, roll dough, cut into shapes, bake for a specified time, and cool on a wire rack.
- Banking transactions: Banks use algorithms and flowcharts to process transactions and manage customer accounts. For example, a flowchart might represent the steps involved in processing a customer deposit, including verifying the customer’s identity, verifying the deposit amount, updating the customer’s account balance, and printing a receipt.
- GPS navigation: GPS navigation systems use algorithms and flowcharts to determine the most efficient route to a destination. For example, a flowchart might represent the steps involved in calculating the shortest route, including determining the starting and ending points, considering factors such as traffic and road conditions, and providing turn-by-turn instructions.
- Sorting and searching algorithms: Sorting and searching algorithms are commonly used in real life to organize and find information. For example, a search algorithm might be used to find a specific item in a large database, while a sorting algorithm might be used to sort a list of names alphabetically.
- Manufacturing processes: Manufacturing processes often use algorithms and flowcharts to represent the steps involved in producing a product. For example, a flowchart might represent the steps involved in making a car, including assembling the engine, installing the transmission, adding the wheels and body, and painting the car.

These are just a few examples of how algorithms and flowcharts are used in real life to solve problems and automate processes