CS Pathfinder Logo CS Pathfinder

Unit 2 · Practice Programs

Practice Programs on Control Structures, Strings and Lists

Challenge yourself with standard practice programs on loops, conditions, lists, and strings in Python.

Learning Objectives

By the end of this lesson, you will be able to:

  • Apply loops and conditional statements to solve classic programming problems.
  • Implement algorithms for factorial, Fibonacci sequence, and prime number checking.
  • Use string slicing and list manipulation techniques to check for palindromes and anagrams.
  • Analyze the logic and trace the execution of these standard algorithms.
  • Understand the importance of edge cases (e.g., input is 0, 1, or negative) in problem-solving.

Prerequisites

To effectively solve these problems, you should be comfortable with:

  • `if-elif-else` statements.
  • `for` and `while` loops.
  • String and list indexing and slicing.
  • Basic arithmetic and logical operators.

Introduction

The best way to master programming concepts is to apply them to solve real problems. This chapter presents five classic exercises that are fundamental to computer science and frequently appear in university exams and technical interviews.

Each program is a mini-challenge that tests your understanding of control structures (loops, conditionals), data manipulation (strings, lists), and algorithmic thinking. Review the code, analyze the logic, and try to write them yourself.

Practice Programs
Figure 2.20 — Consolidating programming foundations through problem solving.

Table of Contents

1. Factorial of a Number

Compute the factorial of a positive integer (e.g., 5! = 5 * 4 * 3 * 2 * 1 = 120) using a loop:

num = 5
factorial = 1

if num < 0:
    print("Factorial does not exist for negative numbers.")
elif num == 0:
    print("Factorial of 0 is 1")
else:
    for i in range(1, num + 1):
        factorial *= i
    print(f"Factorial of {num} is {factorial}")
# Output: Factorial of 5 is 120

Logic Explanation

  1. Initialize a variable `factorial` to 1. This is the multiplicative identity; starting with 0 would make the final result 0.
  2. Handle edge cases: The factorial of 0 is 1, and factorials are not defined for negative numbers.
  3. Use a `for` loop that iterates from 1 up to and including `num`.
  4. In each iteration, multiply the current `factorial` value by the loop counter `i`.
  5. After the loop finishes, `factorial` holds the final result.

Time Complexity

The loop runs `n` times, so the time complexity is O(n).

2. Fibonacci Sequence

Generate the Fibonacci sequence (0, 1, 1, 2, 3, 5, 8, ...) up to N terms:

n_terms = 7
n1, n2 = 0, 1
count = 0

if n_terms <= 0:
    print("Please enter a positive integer.")
else:
    print("Fibonacci sequence:")
    while count < n_terms:
        print(n1, end=" ")
        nth = n1 + n2
        n1 = n2
        n2 = nth
        count += 1
# Output: 0 1 1 2 3 5 8

Logic Explanation

  1. Initialize the first two terms, `n1 = 0` and `n2 = 1`.
  2. Use a `while` loop that runs as long as the `count` of terms printed is less than `n_terms`.
  3. Inside the loop, print the current first term `n1`.
  4. Calculate the next term by adding the previous two: `nth = n1 + n2`.
  5. Update the two previous terms for the next iteration: `n1` becomes `n2`, and `n2` becomes the new `nth` term.
  6. Increment the `count`.

Time Complexity

The loop runs `n` times to generate `n` terms, so the time complexity is O(n).

3. Prime Number Check

Verify whether a number is prime (only divisible by 1 and itself) using loop factors:

num = 11
is_prime = True

if num <= 1:
    is_prime = False
else:
    for i in range(2, int(num**0.5) + 1):
        if num % i == 0:
            is_prime = False
            break

if is_prime:
    print(num, "is a Prime Number")
else:
    print(num, "is not a Prime Number")
# Output: 11 is a Prime Number

Logic Explanation

  1. Use a boolean flag `is_prime`, initialized to `True`. Assume the number is prime until proven otherwise.
  2. Handle edge cases: Numbers less than or equal to 1 are not prime.
  3. Loop from 2 up to the square root of `num`. We only need to check factors up to the square root because if a number `n` has a factor larger than its square root, it must also have a factor smaller than it.
  4. In each iteration, check if `num` is divisible by the current loop number `i`.
  5. If it is divisible, the number is not prime. Flip the flag to `False` and use `break` to exit the loop immediately, as no more checks are needed.
  6. After the loop, check the final state of the `is_prime` flag to print the result.

Time Complexity

The loop runs up to the square root of `n`, making this a very efficient algorithm with a time complexity of O(sqrt(n)).

4. String Palindrome Check

Check if a word reads the same forward and backward using string slicing:

word = "radar"
reversed_word = word[::-1]

if word == reversed_word:
    print(word, "is a Palindrome")
else:
    print(word, "is not a Palindrome")
# Output: radar is a Palindrome

Logic Explanation

  1. The core of this solution is Python's powerful slicing feature.
  2. The slice `word[::-1]` creates a reversed copy of the string.
  3. The `if` statement directly compares the original string with its reversed version.
  4. If they are identical, the string is a palindrome.

Time Complexity

Reversing the string takes O(n) time, where n is the length of the string. The comparison also takes O(n). The overall complexity is O(n).

5. Anagram Check

Verify if two strings are anagrams (formed by rearranging the characters of another string, like "listen" and "silent"):

str1 = "listen"
str2 = "silent"

if sorted(str1) == sorted(str2):
    print(str1, "and", str2, "are Anagrams")
else:
    print(str1, "and", str2, "are not Anagrams")
# Output: listen and silent are Anagrams

Logic Explanation

  1. The logic relies on a simple but powerful idea: if two strings are anagrams, they must contain the exact same characters with the exact same frequencies.
  2. Therefore, if we sort the characters of both strings, the resulting lists of characters should be identical.
  3. The `sorted()` function takes an iterable (like a string) and returns a new sorted list of its items (characters).
  4. The `if` statement compares the two sorted lists. If they are equal, the strings are anagrams.

Time Complexity

The dominant operation is sorting. If the length of the strings is `n`, the time complexity of sorting is typically O(n log n).

Exam Corner: Key Questions & Concepts

These programs are staples in technical assessments. Focus on these areas.

University Exam Questions

  • Write a Python program to find the factorial of a number.
  • Write a program to generate the first N terms of the Fibonacci series.
  • Write a program to check if a given number is prime or not.
  • Explain how to check for a palindrome using string slicing.
  • What is an anagram? Write a program to check if two strings are anagrams.

Interview Questions

  • Can you write the factorial program using recursion? What are the trade-offs?
  • How would you optimize the prime number check for very large numbers?
  • What is the time complexity of your palindrome/anagram solution? Can you do better? (Hint: For anagrams, a dictionary/hash map can achieve O(n)).
  • How would you handle spaces and capitalization in the palindrome/anagram checks?

Summary

Applying foundational concepts to classic problems is the best way to build programming fluency. The factorial and Fibonacci problems test your ability to use loops and manage state. The prime number check introduces algorithmic optimization (checking up to the square root). Finally, palindrome and anagram checks demonstrate the power of Python's built-in data structure manipulations (slicing and sorting) to arrive at elegant solutions.

Python Programming Handwritten Notes

Master Python Programming with Easy Handwritten Notes – Perfect for Interviews, Placements, GATE & Exams.