Current Affairs updated daily
KalviGavaniKalviGavani
Class 11 · Tamil Nadu State Board

Composition Decomposition Exercise Solutions | KalviGavani

TN Class 11 CS Composition and Decomposition solutions: combining functions, breaking down problems, with worked examples and exam tips.

Updated 15 June 202626 min read

Composition and Decomposition — Exercise Solutions

1. How to Use This Page

Welcome to the complete exercise solutions for the Composition and Decomposition chapter from the TN State Board Class 11 Computer Science textbook (Samacheer Kalvi). Here is how to get the most out of this page:

  • Read the Key Concepts Recap first to brush up on definitions, formulas, and Python examples before attempting the exercises.
  • Try each question on your own before reading the solution. Cover the answer with your hand and attempt it honestly.
  • Check the explanations — especially for MCQs and True or False — because understanding why an answer is correct matters more than memorising it.
  • Use the Common Mistakes and Exam Checklist sections for quick last-minute revision before your exam.
  • Bookmark this page and revisit it during revision — repetition builds confidence.

2. Key Concepts (Quick Recap)

2.1 Decomposition

Decomposition is the process of breaking a complex problem into smaller, manageable sub-problems that can be solved independently.

AspectDetails
DefinitionDividing a large problem into smaller parts
PurposeSimplifies solving, allows parallel work, easier debugging
Also calledProblem decomposition, divide-and-conquer
Key ideaEach sub-problem should be self-contained and solvable on its own
# Decomposition example: Student report card
# Instead of writing one massive function, we decompose:

def calculate_total(marks):
    return sum(marks)

def calculate_average(total, count):
    return total / count

def determine_grade(average):
    if average >= 90:
        return "A+"
    elif average >= 80:
        return "A"
    elif average >= 70:
        return "B"
    elif average >= 60:
        return "C"
    else:
        return "D"

def generate_report(name, marks):
    total = calculate_total(marks)
    average = calculate_average(total, len(marks))
    grade = determine_grade(average)
    return f"Student: {name}, Total: {total}, Average: {average:.1f}, Grade: {grade}"

2.2 Composition

Composition is the process of combining two or more simple functions to build a more complex function. The output of one function becomes the input of the next.

AspectDetails
DefinitionCombining functions so that output of one is input of another
Notationf ∘ g (read as "f composed with g")
Formula(f ∘ g)(x) = f(g(x))
Key ideaBuild complex behaviour from simple, reusable pieces
# Composition example: combining functions
def add_two(x):
    return x + 2

def multiply_by_three(x):
    return x * 3

# Composition: multiply_by_three(add_two(x))
# This is the same as (x + 2) * 3

def composed(x):
    return multiply_by_three(add_two(x))

print(composed(5))  # (5 + 2) * 3 = 21

2.3 Top-Down Design

Top-down design (also called stepwise refinement) starts with the overall problem and progressively breaks it down into smaller sub-problems.

StepDescription
1Identify the main problem
2Break it into major sub-problems
3Break each sub-problem further
4Continue until each piece is simple enough to code directly
# Top-down design example: Library Management System
# Level 0: Library Management System
#   Level 1: Book Management, Member Management, Transaction Management
#     Level 2 (under Book Management): Add Book, Search Book, Delete Book
#     Level 2 (under Member Management): Register Member, Update Member, Remove Member
#     Level 2 (under Transaction): Issue Book, Return Book, Calculate Fine

def add_book(title, author, isbn):
    """Lowest level — directly implementable."""
    return {"title": title, "author": author, "isbn": isbn, "available": True}

def search_book(books, isbn):
    for book in books:
        if book["isbn"] == isbn:
            return book
    return None

def book_management(books, action, **kwargs):
    """Composed from lower-level functions."""
    if action == "add":
        books.append(add_book(kwargs["title"], kwargs["author"], kwargs["isbn"]))
    elif action == "search":
        return search_book(books, kwargs["isbn"])
    return books

2.4 Bottom-Up Design

Bottom-up design starts with the smallest, simplest components and combines them into larger structures.

# Bottom-up approach: building a calculator from atomic operations

def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

def multiply(a, b):
    return a * b

def divide(a, b):
    if b == 0:
        raise ValueError("Cannot divide by zero")
    return a / b

# Compose into higher-level operations
def percentage(part, whole):
    return multiply(divide(part, whole), 100)

def average(numbers):
    total = sum(numbers)
    return divide(total, len(numbers))

2.5 Modular Programming

Modular programming organises code into separate, independent modules, each handling a specific task.

BenefitExplanation
ReusabilityModules can be reused across programs
MaintainabilityChanges in one module do not affect others
ReadabilityEach module has a single, clear purpose
TestabilityModules can be tested independently
TeamworkDifferent developers can work on different modules
# Modular programming example: separate modules for a student system

# module_math.py
def calculate_average(marks):
    return sum(marks) / len(marks)

def calculate_percentage(marks, max_marks):
    return (sum(marks) / max_marks) * 100

# module_display.py
def display_report(name, average, grade):
    print(f"Student: {name}")
    print(f"Average: {average:.2f}")
    print(f"Grade: {grade}")

# main.py — composes the modules
from module_math import calculate_average
from module_display import display_report

def main():
    marks = [85, 90, 78, 92, 88]
    avg = calculate_average(marks)
    grade = "A" if avg >= 80 else "B"
    display_report("Kumar", avg, grade)

main()

2.6 Function Composition Rules

RuleMathematical FormPython Equivalent
Associative(f ∘ g) ∘ h = f ∘ (g ∘ h)f(g(h(x))) is unambiguous
Not commutativef ∘ g ≠ g ∘ f (generally)add_two(multiply_by_three(5)) ≠ multiply_by_three(add_two(5))
Identityid ∘ f = f ∘ id = flambda x: x as identity function
Order mattersf ∘ g means apply g first, then fInner function executes first

3. I. Choose the Best Answer (MCQs)

Question 1

The process of breaking a complex problem into smaller, manageable sub-problems is called:

(a) Composition (b) Decomposition (c) Abstraction (d) Encapsulation

Answer(b) Decomposition
ExplanationDecomposition means "breaking down." When we take a complex problem and divide it into smaller, independent sub-problems, we are performing decomposition. Composition is the opposite — combining smaller parts. Abstraction hides details, and encapsulation bundles data with methods.

Question 2

If f(x) = x + 3 and g(x) = x × 2, then (g ∘ f)(4) equals:

(a) 11 (b) 14 (c) 7 (d) 8

Answer(b) 14
Explanation(g ∘ f)(x) = g(f(x)). First apply f: f(4) = 4 + 3 = 7. Then apply g: g(7) = 7 × 2 = 14. Note that (f ∘ g)(4) = f(g(4)) = f(8) = 8 + 3 = 11, which is different — composition is not commutative.

Question 3

Which of the following is an advantage of modular programming?

(a) Code becomes longer (b) Modules cannot be reused (c) Easier debugging and testing (d) Programs run slower

Answer(c) Easier debugging and testing
ExplanationModular programming divides a program into independent modules. Each module can be tested and debugged separately, making the overall process easier. Modules also promote code reuse, reduce duplication, and improve readability.

Question 4

In top-down design, problem solving begins with:

(a) The smallest sub-problems (b) Individual lines of code (c) The overall problem at the highest level (d) Data structures first

Answer(c) The overall problem at the highest level
ExplanationTop-down design starts from the big picture — the overall problem — and progressively refines it into smaller sub-problems. This is the opposite of bottom-up design, which starts with the smallest components.

Question 5

Which of the following statements about function composition is TRUE?

(a) f ∘ g is always equal to g ∘ f (b) The order of composition does not matter (c) Composition is associative: (f ∘ g) ∘ h = f ∘ (g ∘ h) (d) Composition requires all functions to have the same number of parameters

Answer(c) Composition is associative: (f ∘ g) ∘ h = f ∘ (g ∘ h)
ExplanationComposition is associative — the grouping does not affect the result. However, composition is NOT commutative (f ∘ g ≠ g ∘ f in general), so the order matters. The number of parameters must match between output and input, but the functions need not have the same total number of parameters.

Question 6

Which approach starts by building the smallest components first and then combining them?

(a) Top-down design (b) Bottom-up design (c) Waterfall model (d) Spiral model

Answer(b) Bottom-up design
ExplanationBottom-up design begins with the smallest, simplest units and combines them into larger components. Top-down does the opposite — starting from the overall problem and breaking it down.

Question 7

In the composition f(g(h(x))), which function is executed first?

(a) f (b) g (c) h (d) All simultaneously

Answer(c) h
ExplanationIn a composed function, the innermost function executes first. The order is: h(x) first, then g applied to the result of h, then f applied to the result of g. Think of it like peeling an onion — you start from the inside.

Question 8

Decomposition helps in problem solving because:

(a) It makes the problem larger (b) It allows sub-problems to be solved independently (c) It eliminates the need for algorithms (d) It combines all problems into one

Answer(b) It allows sub-problems to be solved independently
ExplanationThe key benefit of decomposition is that each sub-problem can be tackled on its own. This enables parallel work, simplifies debugging, and makes the overall problem more manageable. It does not eliminate the need for algorithms — each sub-problem still needs an algorithmic solution.

4. II. Fill in the Blanks

1. The process of breaking a complex problem into smaller sub-problems is called decomposition.

2. The process of combining two or more functions to create a new function is called composition.

3. In the composition f ∘ g, the function g is executed first.

4. Composition is associative but not commutative.

5. The design approach that starts from the overall problem and refines it step by step is called top-down design.

6. The design approach that starts from the smallest components and combines them is called bottom-up design.

7. A module is a self-contained unit of code that performs a specific task.

8. In function composition (f ∘ g)(x), the output of g becomes the input of f.

9. The identity function id(x) satisfies the property: f ∘ id = id ∘ f = f.

10. Decomposition promotes parallel working because different people can solve different sub-problems at the same time.

11. Modular programming improves code reusability because a module written for one program can be used in another.

12. In top-down design, the process of progressively refining a problem into smaller parts is called stepwise refinement.


5. III. True or False

Statement 1

Decomposition and composition are opposite processes.

AnswerTrue
ExplanationDecomposition breaks a problem into smaller parts, while composition combines smaller parts to form a whole. They are complementary and opposite processes.

Statement 2

Function composition is commutative, i.e., f ∘ g = g ∘ f for all functions f and g.

AnswerFalse

Correction: Function composition is not commutative. In general, f ∘ g ≠ g ∘ f. For example, if f(x) = x + 2 and g(x) = x × 3, then f(g(1)) = 5 but g(f(1)) = 9.


Statement 3

Top-down design is also known as stepwise refinement.

AnswerTrue
ExplanationTop-down design progressively refines a problem by breaking it into smaller sub-problems step by step, which is why it is also called stepwise refinement.

Statement 4

In modular programming, a change in one module always requires changes in all other modules.

AnswerFalse

Correction: One of the key advantages of modular programming is independence — a change in one module does not necessarily require changes in others, as long as the interface (inputs and outputs) remains the same.


Statement 5

The identity function id(x) = x acts as the neutral element in function composition.

AnswerTrue
ExplanationJust as 0 is the additive identity and 1 is the multiplicative identity in arithmetic, the identity function id(x) = x is the identity element for composition: f ∘ id = id ∘ f = f.

Statement 6

Bottom-up design starts with the main problem and then breaks it down.

AnswerFalse

Correction: Bottom-up design starts with the smallest components and builds upward. It is top-down design that starts with the main problem and breaks it down.


Statement 7

Decomposition allows multiple people to work on different sub-problems simultaneously.

AnswerTrue
ExplanationSince each sub-problem is independent after decomposition, different team members can work on different parts at the same time, enabling parallel development.

6. IV. Match the Following

Match the items in Column A with the correct items in Column B:

#Column A#Column B
1DecompositionaCombining functions to build a complex function
2CompositionbBreaking a problem into sub-problems
3Top-down designcBuilding from small components to a whole
4Bottom-up designdStarting from the overall problem and refining
5Modular programmingeSelf-contained, independent code units
6Identity functionfid(x) = x, neutral element of composition
7Stepwise refinementgProgressive detail addition in top-down design
Answer
Column AMatchColumn B
1. Decomposition→ bBreaking a problem into sub-problems
2. Composition→ aCombining functions to build a complex function
3. Top-down design→ dStarting from the overall problem and refining
4. Bottom-up design→ cBuilding from small components to a whole
5. Modular programming→ eSelf-contained, independent code units
6. Identity function→ fid(x) = x, neutral element of composition
7. Stepwise refinement→ gProgressive detail addition in top-down design

7. V. Answer Briefly (2-Mark Questions)

Question 1

Define decomposition with an example.

Answer

Decomposition is the process of breaking a complex problem into smaller, manageable sub-problems that can be solved independently.

Example: Consider the problem of creating a student report card. We can decompose it into:

  • Sub-problem 1: Calculate total marks
  • Sub-problem 2: Calculate average
  • Sub-problem 3: Determine grade based on average
  • Sub-problem 4: Display the report

Each sub-problem can be solved independently and then combined to produce the final report card.


Question 2

Define composition with an example.

Answer

Composition is the process of combining two or more functions so that the output of one function becomes the input of another, creating a new function.

Example: If f(x) = x + 5 and g(x) = x × 2, then the composition g ∘ f is:

  • (g ∘ f)(x) = g(f(x)) = g(x + 5) = (x + 5) × 2

In Python:

def f(x):
    return x + 5

def g(x):
    return x * 2

# Composed: g(f(x))
result = g(f(3))  # g(f(3)) = g(8) = 16

Question 3

What is the difference between top-down and bottom-up design?

Answer
AspectTop-Down DesignBottom-Up Design
Starting pointOverall problemSmallest components
DirectionFrom general to specificFrom specific to general
ProcessBreak down (decompose)Build up (compose)
AdvantageClear overview firstReusable components first
RiskMay miss low-level detailsMay lose sight of the big picture

Top-down design starts with the big picture and refines it step by step. Bottom-up design starts with the smallest building blocks and combines them upward.


Question 4

What is modular programming? List two advantages.

Answer

Modular programming is an approach where a program is divided into separate, independent modules, each responsible for a specific task or functionality.

Two advantages: 1. Reusability: A module written for one program can be reused in another program without modification, saving development time. 2. Maintainability: When a bug is found or a change is needed, only the relevant module needs to be modified. Other modules remain unaffected, reducing the risk of introducing new bugs.


Question 5

Show that composition is not commutative using an example.

Answer

Composition is not commutative: f ∘ g ≠ g ∘ f in general.

Let f(x) = x + 3 and g(x) = x × 2.

  • f ∘ g applied to x = 4:
  • (f ∘ g)(4) = f(g(4)) = f(8) = 8 + 3 = 11
  • g ∘ f applied to x = 4:
  • (g ∘ f)(4) = g(f(4)) = g(7) = 7 × 2 = 14

Since 11 ≠ 14, f ∘ g ≠ g ∘ f. Hence, composition is not commutative.


8. VI. Answer in Detail (5-Mark Questions)

Question 1

Explain the process of decomposition with a suitable example. Discuss its advantages.

Answer

Decomposition is the systematic process of breaking a complex problem into smaller, independent sub-problems that are easier to understand, solve, and manage.

Process of Decomposition:

1. Identify the main problem: Clearly define what needs to be solved. 2. Identify major sub-problems: Break the main problem into 2–5 major parts. 3. Break down further: Divide each sub-problem further until each piece is simple enough to be solved directly. 4. Solve each sub-problem: Write code or design algorithms for each piece. 5. Compose the solutions: Combine the solutions of sub-problems to form the complete solution.

Detailed Example — Building a School Management System:

School Management System (Main Problem) ├── Student Management │ ├── Add Student │ ├── Search Student │ └── Update Student ├── Attendance Tracking │ ├── Mark Attendance │ ├── View Attendance │ └── Generate Reports └── Exam Management ├── Enter Marks ├── Calculate Results └── Generate Report Cards

Python Implementation:

# Sub-problem 1: Student Management
def add_student(students, name, roll_no):
    students.append({"name": name, "roll_no": roll_no})
    return students

def search_student(students, roll_no):
    for student in students:
        if student["roll_no"] == roll_no:
            return student
    return None

# Sub-problem 2: Attendance
def mark_attendance(records, roll_no, status):
    records.append({"roll_no": roll_no, "status": status})
    return records

# Sub-problem 3: Exam Results
def calculate_average(marks):
    return sum(marks) / len(marks)

def determine_grade(average):
    if average >= 90:
        return "A+"
    elif average >= 80:
        return "A"
    elif average >= 70:
        return "B"
    elif average >= 60:
        return "C"
    else:
        return "D"

# Composed solution
def generate_report_card(student, marks):
    avg = calculate_average(marks)
    grade = determine_grade(avg)
    return {
        "name": student["name"],
        "roll_no": student["roll_no"],
        "average": avg,
        "grade": grade
    }

Advantages of Decomposition:

1. Simplifies complex problems: Each sub-problem is smaller and easier to understand. 2. Enables parallel work: Different team members can work on different sub-problems simultaneously. 3. Easier debugging: When an error occurs, it can be isolated to a specific sub-problem. 4. Improves code organisation: Code is structured logically with clear responsibilities. 5. Promotes reuse: Sub-problem solutions can be reused in other contexts.


Question 2

Explain function composition with rules and examples. Show how composition is associative but not commutative.

Answer

Function Composition is the process of combining two or more functions to create a new function, where the output of one function becomes the input of the next.

Mathematical Definition:

Given two functions f and g, the composition f ∘ g is defined as:

(f ∘ g)(x) = f(g(x))

This means g is applied first, and then f is applied to the result.

Python Implementation:

# Define simple functions
def double(x):
    return x * 2

def add_five(x):
    return x + 5

def square(x):
    return x ** 2

# Compose: double(add_five(x)) = 2(x + 5)
def compose_2(x):
    return double(add_five(x))

# Compose: square(double(add_five(x))) = (2(x + 5))^2
def compose_3(x):
    return square(double(add_five(x)))

print(compose_2(3))   # double(add_five(3)) = double(8) = 16
print(compose_3(3))   # square(double(add_five(3))) = square(16) = 256

General Composition Function in Python:

def compose(f, g):
    """Return a function that computes f(g(x))."""
    return lambda x: f(g(x))

# Usage
h = compose(double, add_five)
print(h(3))  # 16

# Chain multiple compositions
from functools import reduce

def compose_all(*functions):
    return reduce(compose, functions)

composed_fn = compose_all(square, double, add_five)
print(composed_fn(3))  # square(double(add_five(3))) = 256

Rule 1: Composition is Associative

(f ∘ g) ∘ h = f ∘ (g ∘ h)

This means the grouping does not matter. Both evaluate to f(g(h(x))).

Proof by example:

Let f(x) = x², g(x) = x + 1, h(x) = x × 2. Evaluate at x = 3.

  • (f ∘ g) ∘ h: First compute (f ∘ g)(x) = f(g(x)) = (x + 1)², then apply h first: (f ∘ g)(h(3)) = (6 + 1)² = 49
  • f ∘ (g ∘ h): First compute (g ∘ h)(x) = g(h(x)) = 2x + 1, then: f((g ∘ h)(3)) = f(7) = 49

Both give 49 — associative property holds.

Rule 2: Composition is NOT Commutative

f ∘ g ≠ g ∘ f (in general)

Proof by example:

Let f(x) = x + 3 and g(x) = x × 2. Evaluate at x = 5.

  • f ∘ g: f(g(5)) = f(10) = 10 + 3 = 13
  • g ∘ f: g(f(5)) = g(8) = 8 × 2 = 16

Since 13 ≠ 16, composition is not commutative.

Rule 3: Identity Function

The identity function id(x) = x acts as the neutral element:

f ∘ id = id ∘ f = f

identity = lambda x: x  # id(x) = x

# f ∘ id = f
result1 = add_five(identity(5))  # add_five(5) = 10
# id ∘ f = f
result2 = identity(add_five(5))   # identity(10) = 10

Question 3

Compare top-down and bottom-up design approaches. Explain with examples when each is more suitable.

Answer

Top-Down Design (also called stepwise refinement) starts with the overall problem and progressively breaks it down into smaller sub-problems until each is simple enough to implement directly.

Bottom-Up Design starts with the smallest, most basic components and combines them into larger structures until the complete system is built.

Detailed Comparison:

CriterionTop-Down DesignBottom-Up Design
Starting pointThe main/overall problemSmallest functional units
DirectionGeneral → SpecificSpecific → General
ProcessDecompositionComposition
PlanningRequires clear understanding of the wholeCan start with partial understanding
TestingTested at the end (whole system)Tested incrementally (unit by unit)
RiskMay discover late that a sub-problem is infeasibleMay build components that do not integrate well
Best forWell-understood problemsExploratory or research-oriented problems

Top-Down Design Example — Payroll System:

# Level 0: Main problem
def payroll_system(employees):
    """Generate payroll for all employees."""
    results = []
    for emp in employees:
        gross = calculate_gross_pay(emp)
        deductions = calculate_deductions(emp, gross)
        net = calculate_net_pay(gross, deductions)
        results.append(format_payslip(emp, gross, deductions, net))
    return results

# Level 1: Sub-problems
def calculate_gross_pay(emp):
    """Gross = basic + overtime + bonus."""
    basic = emp["basic_pay"]
    overtime = compute_overtime(emp["hours_worked"], emp["rate"])
    bonus = compute_bonus(emp["performance_rating"])
    return basic + overtime + bonus

def calculate_deductions(emp, gross):
    """Deductions = tax + insurance + provident_fund."""
    tax = compute_tax(gross)
    insurance = emp.get("insurance", 0)
    pf = compute_provident_fund(emp["basic_pay"])
    return tax + insurance + pf

def calculate_net_pay(gross, deductions):
    return gross - deductions

# Level 2: Lowest-level functions
def compute_overtime(hours, rate):
    regular_hours = min(hours, 40)
    overtime_hours = max(hours - 40, 0)
    return overtime_hours * rate * 1.5

def compute_tax(gross):
    if gross <= 250000:
        return 0
    elif gross <= 500000:
        return (gross - 250000) * 0.05
    else:
        return 12500 + (gross - 500000) * 0.1

Bottom-Up Design Example — String Utilities Library:

# Start with the smallest utility functions
def reverse_string(s):
    return s[::-1]

def capitalize_words(s):
    return " ".join(word.capitalize() for word in s.split())

def count_vowels(s):
    return sum(1 for ch in s.lower() if ch in "aeiou")

def remove_spaces(s):
    return s.replace(" ", "")

# Compose into higher-level utilities
def is_palindrome(s):
    cleaned = remove_spaces(s).lower()
    return cleaned == reverse_string(cleaned)

def word_statistics(s):
    return {
        "word_count": len(s.split()),
        "vowel_count": count_vowels(s),
        "char_count": len(remove_spaces(s))
    }

# Compose further into a text analysis tool
def analyze_text(text):
    stats = word_statistics(text)
    stats["palindrome_check"] = is_palindrome(text)
    stats["reversed"] = reverse_string(text)
    stats["capitalized"] = capitalize_words(text)
    return stats

When to Use Top-Down:

  • The overall system requirements are clear from the start.
  • The problem has a natural hierarchical structure.
  • You need to present a clear architecture to stakeholders early.

When to Use Bottom-Up:

  • Requirements are not fully known and may evolve.
  • You have reusable components from previous projects.
  • You are building libraries or APIs where low-level correctness is paramount.

In Practice: Most real-world projects use a mixed approach — top-down for overall architecture, bottom-up for reusable utility components.


9. Common Mistakes to Avoid

Mistake 1: Confusing Composition Order

Error: Assuming f ∘ g means "apply f first, then g."

Correction: In f ∘ g, the function closest to the input (g) is applied first. f ∘ g(x) = f(g(x)). Think of it as "g feeds into f." The rightmost function executes first.

# WRONG interpretation
# f ∘ g does NOT mean apply f then g
# f(g(x)) — g is applied FIRST

def f(x):
    return x + 3

def g(x):
    return x * 2

# f ∘ g at x = 4
result = f(g(4))  # f(g(4)) = f(8) = 11  (g applied first)
# NOT g(f(4)) = g(7) = 14

Mistake 2: Assuming Composition is Commutative

Error: Writing f(g(x)) = g(f(x)) without verification.

Correction: Composition is NOT commutative. Always compute f(g(x)) and g(f(x)) separately. They are equal only in special cases (e.g., when both functions are the identity, or when both are powers of x with the same base).


Mistake 3: Confusing Top-Down and Bottom-Up

Error: Saying "top-down design starts with small parts."

Correction: Top-down starts with the big picture (the overall problem) and breaks it down. Bottom-up starts with the small parts and builds up. Remember: Top-down = decompose from the top; Bottom-up = compose from the bottom.


Mistake 4: Not Decomposing Enough

Error: Breaking a problem into only 2 very large sub-problems that are still too complex.

Correction: Continue decomposing until each sub-problem can be solved by a single, straightforward function. If a sub-problem still requires multiple steps or decisions, decompose it further.


Mistake 5: Creating Modules That Are Tightly Coupled

Error: Writing modules that depend heavily on each other's internal details.

Correction: Each module should have a clear, minimal interface (well-defined inputs and outputs). Modules should communicate through their interfaces, not through shared internal state. This ensures that changes in one module do not cascade through the entire program.

# BAD: Tightly coupled
def process_data(data):
    # Directly accesses global variable
    global threshold
    return [x for x in data if x > threshold]

# GOOD: Loosely coupled
def process_data(data, threshold):
    return [x for x in data if x > threshold]

Mistake 6: Forgetting the Identity Function in Composition

Error: Not recognising that the identity function id(x) = x plays a special role.

Correction: The identity function is the neutral element for composition, just as 0 is neutral for addition and 1 is neutral for multiplication. Know that f ∘ id = id ∘ f = f for any function f.


Mistake 7: Writing One Monolithic Function Instead of Composing

Error: Putting all logic into a single long function instead of decomposing and composing.

Correction: Break the logic into small, focused functions and compose them. This improves readability, testability, and reusability.

# BAD: Monolithic
def process_student(name, marks):
    total = sum(marks)
    average = total / len(marks)
    if average >= 90:
        grade = "A+"
    elif average >= 80:
        grade = "A"
    else:
        grade = "B"
    return f"{name}: Total={total}, Avg={average}, Grade={grade}"

# GOOD: Decomposed and composed
def calculate_total(marks):
    return sum(marks)

def calculate_average(marks):
    return calculate_total(marks) / len(marks)

def determine_grade(average):
    if average >= 90:
        return "A+"
    elif average >= 80:
        return "A"
    return "B"

def process_student(name, marks):
    avg = calculate_average(marks)
    grade = determine_grade(avg)
    return f"{name}: Total={calculate_total(marks)}, Avg={avg}, Grade={grade}"

10. Exam Checklist

Before your exam, make sure you can tick off every item below:

  • [ ] Define decomposition — breaking a complex problem into smaller sub-problems.
  • [ ] Define composition — combining functions where output of one becomes input of another.
  • [ ] Know the notation — f ∘ g means f(g(x)); g is applied first.
  • [ ] Composition is associative — (f ∘ g) ∘ h = f ∘ (g ∘ h).
  • [ ] Composition is NOT commutative — f ∘ g ≠ g ∘ f (in general). Be ready to prove with an example.
  • [ ] Identity function — id(x) = x; f ∘ id = id ∘ f = f.
  • [ ] Top-down design — starts from the overall problem, refines downward (stepwise refinement).
  • [ ] Bottom-up design — starts from smallest components, combines upward.
  • [ ] Modular programming — organising code into independent, reusable modules.
  • [ ] Advantages of decomposition — simplification, parallel work, easier debugging, reuse.
  • [ ] Advantages of modular programming — reusability, maintainability, readability, independent testing.
  • [ ] Compute composed functions — given f(x) and g(x), calculate f(g(x)) and g(f(x)) at a given value.
  • [ ] Draw decomposition trees — represent a problem as a tree with sub-problems as branches.
  • [ ] Distinguish top-down vs bottom-up — know when each approach is appropriate.
  • [ ] Trace composed function calls — show step-by-step evaluation of f(g(h(x))).

Remember: Decomposition and composition are two sides of the same coin. Decomposition helps you understand a problem by breaking it apart; composition helps you build a solution by putting pieces together. Master both, and you can tackle problems of any size!

Frequently Asked Questions

Decomposition is the process of breaking a complex problem into smaller, manageable sub-problems that can be solved independently and then combined.
← Browse all Class 11 Exercise Solutions

Other question types — same chapter