Problem solving in programming involves analyzing a problem, designing a solution, implementing the solution, and testing the result. It is the first step in creating a working computer program.
Clearly stating the problem helps define what inputs are required, what processing is needed, and what the expected output should be.
Program design refers to planning the logical steps (algorithm) before coding. Techniques include using flowcharts, pseudocode, and structure diagrams.
Debugging is the process of finding and fixing errors in a program.
Good documentation helps other programmers understand the code. It includes comments in the code, user manuals, and technical specifications.
A graphical representation of the program logic using standard symbols like arrows, decision blocks, and processes.
It shows different conditions and corresponding actions in a table format for clarity in decision-making processes.
An algorithm is a step-by-step set of instructions to solve a specific problem.
Algorithm to find the largest of two numbers: 1. Start 2. Input a, b 3. If a > b then print a is largest else print b is largest 4. Stop
Encourages dividing a program into small, reusable modules or functions. It improves clarity and debugging.
Python is a high-level, interpreted, general-purpose programming language with a focus on readability and simplicity.
# Simple Python Program def greet(): print("Hello, World!") greet()
# Variable and arithmetic operation x = 10 y = 5 print("Sum is:", x + y)
The Python interpreter reads and executes Python code line by line. It can be accessed via the command line or through an IDE like VS Code or IDLE.
Python can be used for arithmetic operations directly in the shell.
# Python as a calculator print(5 + 3) print(10 / 2) print(2 ** 3)
The interactive environment where you type code and see immediate output is called the Python shell.
Python uses indentation (spaces/tabs) to define blocks of code. Incorrect indentation leads to errors.
if 5 > 2: print("5 is greater than 2") # Correct indentation
Literals are fixed values in code, like numbers or text. Strings are enclosed in single or double quotes.
name = "Python" age = 20 print(name, "is", age, "years old")
# Ternary operator example a = 5 b = 10 max_val = a if a > b else b print("Max is:", max_val)
Python files end with .py. You can write code in any text editor or IDE and run it using the Python interpreter.
name = input("Enter your name: ") print("Hello", name)
x = 10 if x > 5: print("x is greater than 5") else: print("x is 5 or less")
for i in range(5): print(i) # While loop i = 0 while i < 3: print(i) i += 1
import sys sys.exit() # exits the program
for i in range(5): if i == 2: continue print(i)
def greet(name): print("Hello", name) greet("Alice")
def greet(name="Guest"): print("Hello", name) greet()
Exceptions can be handled using try-except blocks.
try: x = int(input("Enter number: ")) except ValueError: print("Invalid input!")
Execution depends on conditions using if-else.
Using if-elif-else for multiple conditions.
x = 5 if x > 10: print("Big") elif x == 5: print("Medium") else: print("Small")
x = 5 if x > 0: if x < 10: print("x is between 0 and 10")
def square(n): return n * n print(square(4))
A function that calls itself.
def factorial(n): if n == 1: return 1 else: return n * factorial(n - 1) print(factorial(5))
Recursion occurs when a function calls itself in order to solve a problem. Each recursive call breaks the problem into simpler sub-problems.
# Example of recursion: Factorial function def factorial(n): if n == 1: return 1 else: return n * factorial(n - 1) print(factorial(5))
Each recursive call is placed on the call stack. As the recursion progresses, a new stack frame is created. When the function reaches the base case, it starts unwinding and returns the result.
# Factorial stack diagram representation: # factorial(5) → factorial(4) → factorial(3) → factorial(2) → factorial(1) # Unwinding: factorial(1) → factorial(2) → factorial(3) → factorial(4) → factorial(5)
Multiple assignment allows you to assign values to multiple variables in a single statement.
x, y, z = 10, 20, 30 print(x, y, z)
The `while` loop repeatedly executes a block of code as long as a given condition is true.
# Example of while loop x = 0 while x < 5: print(x) x += 1
Tables are typically represented as lists of lists (two-dimensional arrays) in Python. These can be used to store data in rows and columns.
# Creating a 2D table (list of lists) table = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # Accessing elements print(table[0][1]) # Output: 2
Two-dimensional tables can be useful for storing grids, matrices, or tabular data. You can access elements using two indices: one for the row and one for the column.
# Example of accessing and modifying a 2D table matrix = [[1, 2], [3, 4]] matrix[0][1] = 99 # Change value print(matrix) # Output: [[1, 99], [3, 4]]
A string is a sequence of characters. It is a compound data type because it can hold multiple values (characters).
# Example of a string as a compound data type s = "Hello" print(s[0]) # Output: H
Strings have a length, which can be found using the built-in `len()` function.
s = "Python" print(len(s)) # Output: 6
You can use a `for` loop to traverse a string (or any iterable).
s = "Python" for char in s: print(char)
Strings can be sliced to get substrings. The slicing syntax is s[start:end]
.
s = "Python" print(s[1:4]) # Output: yth
Strings can be compared using relational operators.
s1 = "apple" s2 = "banana" print(s1 == s2) # Output: False print(s1 < s2) # Output: True
The `find()` method returns the index of the first occurrence of a substring. If not found, it returns -1.
s = "Python programming" index = s.find("programming") print(index) # Output: 7
Lists are ordered collections of items in Python. They can hold different data types.
lst = [1, 2, 3, 4] print(lst) # Output: [1, 2, 3, 4]
You can access elements by index and modify them by assigning new values.
lst[0] = 10 print(lst) # Output: [10, 2, 3, 4]
Lists can also be sliced to get sublists.
lst = [1, 2, 3, 4, 5] print(lst[1:4]) # Output: [2, 3, 4]
lst = [1, 2, 3] lst.append(4) print(lst) # Output: [1, 2, 3, 4]
Looping allows us to iterate over list elements. The `for` loop is commonly used for counting elements in a list, and can also be used to iterate through the list to perform specific operations.
# Loop through a list and count the number of elements lst = [1, 2, 3, 4, 5] count = 0 for item in lst: count += 1 print("Total elements:", count)
Each item in a list has an index, which can be used to access elements directly. Indexing starts at 0.
# Accessing elements in a list lst = ['apple', 'banana', 'cherry'] print(lst[0]) # Output: apple print(lst[1]) # Output: banana print(lst[2]) # Output: cherry
The `len()` function returns the number of elements in a list.
# Find the length of a list lst = ['apple', 'banana', 'cherry'] print(len(lst)) # Output: 3
The `in` operator is used to check if an element is present in a list.
# Check membership in a list lst = ['apple', 'banana', 'cherry'] print('banana' in lst) # Output: True print('orange' in lst) # Output: False
You can use `for` loops to iterate over a list and perform operations on each element.
# Example of looping through a list lst = [10, 20, 30, 40] for item in lst: print(item * 2)
Python provides various operations to manipulate lists, such as adding, removing, or modifying elements.
# Adding elements to a list lst = [1, 2, 3] lst.append(4) lst.insert(1, 10) # Insert at index 1 print(lst) # Output: [1, 10, 2, 3, 4] # Removing elements lst.remove(10) # Removes the first occurrence of 10 lst.pop() # Removes the last element print(lst) # Output: [1, 2, 3]
Elements in a list can be deleted using the `del` keyword or the `remove()` method.
# Deleting elements from a list lst = [1, 2, 3, 4] del lst[1] # Removes element at index 1 print(lst) # Output: [1, 3, 4]
Cloning a list allows you to create a new copy of the list. You can use slicing or the `copy()` method to clone a list.
# Cloning a list lst = [1, 2, 3] cloned_lst = lst[:] # Slicing method print(cloned_lst) # Output: [1, 2, 3] # Alternatively, using the copy() method cloned_lst = lst.copy() print(cloned_lst) # Output: [1, 2, 3]
A nested list is a list within another list, allowing you to store more complex data structures.
# Example of a nested list (list of lists) nested_lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] # Accessing elements in a nested list print(nested_lst[0][1]) # Output: 2 print(nested_lst[2][2]) # Output: 9
OOP is a programming paradigm based on the concept of objects. Objects are instances of classes, and methods are functions defined within classes.
# Creating a class and an object class Person: def __init__(self, name, age): self.name = name self.age = age def greet(self): print(f"Hello, my name is {self.name} and I am {self.age} years old.") # Creating an object of the class person1 = Person("Alice", 30) person1.greet() # Output: Hello, my name is Alice and I am 30 years old.
Python has many built-in libraries that provide various functionalities. Some of the commonly used libraries include:
# Example using the math library import math print(math.sqrt(16)) # Output: 4.0
Data structures are a way of organizing and storing data efficiently. Let's look at some common data structures in Python.
Arrays are used to store multiple values in a single variable. In Python, arrays can be represented using lists, as Python does not have a dedicated array data structure.
# Creating an array using a list arr = [1, 2, 3, 4, 5] print(arr) # Output: [1, 2, 3, 4, 5]
Lists in Python are dynamic arrays that can store elements of different types and sizes. They can be modified after creation by adding, removing, or changing elements.
# Creating a list lst = [10, 20, 30, 40] print(lst) # Output: [10, 20, 30, 40]
Sets are unordered collections of unique elements. They do not allow duplicates and are useful for membership tests and mathematical operations like union and intersection.
# Creating a set s = {1, 2, 3, 4} print(s) # Output: {1, 2, 3, 4} # Adding and removing elements s.add(5) s.remove(2) print(s) # Output: {1, 3, 4, 5}
A stack is a collection of elements with two main operations: push (adding an element) and pop (removing an element). It follows the Last In, First Out (LIFO) principle.
# Stack operations using a list stack = [] stack.append(1) # Push stack.append(2) # Push stack.append(3) # Push print(stack) # Output: [1, 2, 3] stack.pop() # Pop print(stack) # Output: [1, 2]
A queue is a collection of elements that follows the First In, First Out (FIFO) principle. Elements are added at the back and removed from the front.
# Queue operations using collections.deque from collections import deque queue = deque() queue.append(1) # Enqueue queue.append(2) # Enqueue queue.append(3) # Enqueue print(queue) # Output: deque([1, 2, 3]) queue.popleft() # Dequeue print(queue) # Output: deque([2, 3])
Searching algorithms are used to find a specific element in a data structure. Below are two common searching algorithms: Linear Search and Binary Search.
Linear search is a simple method that checks every element in a list until the target element is found.
# Linear Search def linear_search(arr, target): for i in range(len(arr)): if arr[i] == target: return i # Return the index of the target element return -1 # Target not found arr = [5, 3, 8, 4, 2] target = 4 result = linear_search(arr, target) print("Element found at index:", result) # Output: Element found at index: 3
Binary search works on sorted arrays. It repeatedly divides the search interval in half. If the target value is less than the middle element, the search continues on the left half, otherwise, it searches the right half.
# Binary Search def binary_search(arr, target): low = 0 high = len(arr) - 1 while low <= high: mid = (low + high) // 2 if arr[mid] == target: return mid # Target found elif arr[mid] < target: low = mid + 1 # Search right half else: high = mid - 1 # Search left half return -1 # Target not found arr = [1, 2, 3, 4, 5, 6, 7, 8] target = 4 result = binary_search(arr, target) print("Element found at index:", result) # Output: Element found at index: 3
Sorting algorithms are used to arrange elements in a specific order, either ascending or descending. Below are three common sorting algorithms: Bubble Sort, Selection Sort, and Insertion Sort.
Bubble sort works by repeatedly stepping through the list, comparing adjacent elements, and swapping them if they are in the wrong order. This process repeats until the list is sorted.
# Bubble Sort def bubble_sort(arr): n = len(arr) for i in range(n): for j in range(0, n-i-1): if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j] # Swap return arr arr = [64, 34, 25, 12, 22, 11, 90] sorted_arr = bubble_sort(arr) print("Sorted array:", sorted_arr) # Output: Sorted array: [11, 12, 22, 25, 34, 64, 90]
Selection sort works by repeatedly finding the minimum element from the unsorted part of the list and swapping it with the first unsorted element.
# Selection Sort def selection_sort(arr): for i in range(len(arr)): min_idx = i for j in range(i+1, len(arr)): if arr[j] < arr[min_idx]: min_idx = j arr[i], arr[min_idx] = arr[min_idx], arr[i] # Swap return arr arr = [64, 34, 25, 12, 22, 11, 90] sorted_arr = selection_sort(arr) print("Sorted array:", sorted_arr) # Output: Sorted array: [11, 12, 22, 25, 34, 64, 90]
Insertion sort works by taking each element and inserting it into the correct position in the sorted part of the list.
# Insertion Sort def insertion_sort(arr): for i in range(1, len(arr)): key = arr[i] j = i-1 while j >= 0 and key < arr[j]: arr[j+1] = arr[j] j -= 1 arr[j+1] = key return arr arr = [64, 34, 25, 12, 22, 11, 90] sorted_arr = insertion_sort(arr) print("Sorted array:", sorted_arr) # Output: Sorted array: [11, 12, 22, 25, 34, 64, 90]