Answers for Python May 2023 QP

GE3151 | Python Question Paper — Solved
✦ Exam-ready answer bank · April / May 2023

Problem Solving
with Python.

GE3151 · First Semester · Regulations 2021. Clear 2-mark definitions, structured 8/16-mark explanations, algorithms, flowchart, pseudocode and runnable Python programs — including both alternatives in the paper.

10Part A answers
All ORsBoth choices solved
Python 3Program examples
100 marksPaper coverage
Section 01 · 10 × 2 = 20 marks

Part A — Short answers

Concise points you can reproduce in a two-mark answer.

01

Qualities of a good algorithm

2 marks

A good algorithm should have these characteristics:

  • Correctness: produces the expected result.
  • Finiteness: terminates after a finite number of steps.
  • Definiteness: every step is clear and unambiguous.
  • Input and output: accepts zero or more inputs and produces at least one result where required.
  • Effectiveness: steps are basic and executable.
  • Efficiency: uses reasonable time and memory.
02

Strategies for developing an algorithm

2 marks

Common problem-solving strategies include:

  • Top-down: split a large problem into smaller subproblems.
  • Bottom-up: build a solution from smaller components.
  • Divide and conquer: divide, solve subproblems, then combine.
  • Greedy: choose the best local option at each step.
  • Dynamic programming: store and reuse results of overlapping subproblems.
  • Backtracking / brute force: explore possible choices or systematically test candidates.

In a short answer, state the strategies taught in your class notes if the lecturer uses a narrower list.

03

Rules for writing an identifier

2 marks
  • Must begin with a letter (A–Z, a–z) or underscore (_).
  • After the first character, may contain letters, digits and underscores.
  • Cannot contain spaces or punctuation such as -, @ or !.
  • Cannot be a Python keyword such as if, for or class.
  • Identifiers are case-sensitive: total and Total differ.

Valid student_1, _count   Invalid: 1student, student-name

04

Types of arguments in Python

2 marks

The common kinds are:

  1. Positional: matched by order, e.g. add(2, 3).
  2. Keyword: passed by parameter name, e.g. add(a=2, b=3).
  3. Default: parameter has a preset value if omitted.
  4. Variable-length: *args accepts extra positional arguments and **kwargs accepts extra keyword arguments.
05

Return value and composition

2 marks

Return value: the result a function sends back to its caller using return.

Function composition: combining function calls so that the output of one function becomes the input of another.

Python example
def double(x):
    return 2 * x

def add_one(x):
    return x + 1

result = add_one(double(3))  # 7

The function double returns 6; then add_one receives that result and returns 7.

06

String immutability

2 marks

Strings in Python are immutable, meaning their characters cannot be changed in place after the string is created. Operations that appear to modify a string create a new string.

Example
s = "cat"
# s[0] = "b"  # TypeError
s = "b" + s[1:]  # creates "bat"
07

Cloning in a list

2 marks

Cloning creates a separate list object containing the same elements as the original list. For a shallow copy, use slicing or copy().

Example
a = [10, 20, 30]
b = a[:]       # or: b = a.copy()
b[0] = 99
print(a)  # [10, 20, 30]
print(b)  # [99, 20, 30]

A shallow copy does not recursively copy nested mutable objects.

08

Benefit of tuple assignment

2 marks

Tuple assignment (sequence unpacking) assigns multiple variables in one statement. It makes code concise and allows variables to be swapped without a temporary variable.

Example
a, b = 5, 9
a, b = b, a
print(a, b)  # 9 5
09

How to delete a file in Python

2 marks

Use os.remove() or Path.unlink(). Ensure the path is correct and handle possible file errors.

Example
import os

os.remove("old_file.txt")

Deleting a file is destructive. Check the path before running this code.

10

Command-line arguments

2 marks

Command-line arguments are values supplied after the script name when running a program. The sys.argv list in the sys module stores them as strings; sys.argv[0] is the script name.

hello.py
import sys
print("Hello", sys.argv[1])

Run with python hello.py Ravi; output: Hello Ravi.

Section 02 · Question 11

Algorithms, recursion & languages

Both (a) and (b) alternatives are answered below.

11(a)(i)

Iteration and recursion with examples

8 marks

Iteration repeats a block using a loop such as for or while. Recursion solves a problem by having a function call itself on a smaller input. A recursive function must have a base case to stop the calls.

IterationRecursion
Uses loops.Uses repeated function calls.
Stops when the loop condition becomes false.Stops when the base case is reached.
Usually uses constant call-stack space.Uses call-stack space for each pending call.
Often efficient for straightforward repetition.Can express naturally recursive problems clearly.

Example: factorial where n! = n × (n−1) × … × 1 and 0! = 1.

Iterative and recursive factorial
def factorial_iterative(n):
    if n < 0:
        raise ValueError("n must be non-negative")
    result = 1
    for i in range(2, n + 1):
        result *= i
    return result


def factorial_recursive(n):
    if n < 0:
        raise ValueError("n must be non-negative")
    if n == 0 or n == 1:  # base case
        return 1
    return n * factorial_recursive(n - 1)

print(factorial_iterative(5))  # 120
print(factorial_recursive(5))  # 120

Conclusion: both methods calculate the same result. Iteration avoids recursive call overhead; recursion can make a naturally recursive definition easier to understand.

11(a)(ii)

Algorithm and flowchart for net salary

8 marks

Assumption: the question gives no particular salary percentages. Read the earnings components and total deductions as inputs.

Algorithm

  1. Start.
  2. Read basic pay, allowances and deductions.
  3. Calculate gross = basic + allowances.
  4. Calculate net = gross − deductions.
  5. Display gross and net salary.
  6. Stop.
START
↓
Input basic pay, allowances, deductions
↓
gross = basic + allowances
↓
net = gross − deductions
↓
Display gross and net salary
↓
STOP
Python implementation
basic = float(input("Enter basic pay: "))
allowances = float(input("Enter total allowances: "))
deductions = float(input("Enter total deductions: "))

gross = basic + allowances
net = gross - deductions

print(f"Gross salary: {gross:.2f}")
print(f"Net salary: {net:.2f}")
11(b)(i)

Machine, assembly and high-level languages

8 marks
FeatureMachine languageAssembly languageHigh-level language
RepresentationBinary bits (0 and 1)Mnemonics such as MOVEnglish-like statements, e.g. Python
Hardware dependenceMachine-specificMachine-specificUsually more portable
TranslatorExecuted by CPUAssemblerCompiler or interpreter (implementation-dependent)
Ease of writingVery difficultMore readable than machine codeGenerally easiest to write and maintain
ControlDirect low-level controlClose hardware controlHigher abstraction from hardware

Examples: machine code bytes; assembly instructions; Python, C, Java. High-level languages still need translation or a runtime before execution by the machine.

11(b)(ii)

Pseudocode: maximum in a list & Towers of Hanoi

8 marks

1. Find maximum in a non-empty list

Pseudocode
ALGORITHM FindMaximum(A)
    IF length(A) = 0 THEN
        REPORT "List is empty" and STOP
    max ← A[0]
    FOR each item x in A from the second item
        IF x > max THEN
            max ← x
        END IF
    END FOR
    OUTPUT max
END ALGORITHM

2. Towers of Hanoi — move n disks from source to destination using an auxiliary peg; move only one disk at a time and never put a larger disk on a smaller one.

Pseudocode
PROCEDURE Hanoi(n, source, auxiliary, destination)
    IF n = 1 THEN
        OUTPUT "Move disk 1 from", source, "to", destination
    ELSE
        Hanoi(n - 1, source, destination, auxiliary)
        OUTPUT "Move disk", n, "from", source, "to", destination
        Hanoi(n - 1, auxiliary, source, destination)
    END IF
END PROCEDURE

The number of moves for n disks is 2ⁿ − 1.

Section 03 · Question 12

Variables and operators

Naming rules, swapping, precedence and leap years.

12(a)(i)

Rules for naming variables, with examples

8 marks
  1. A variable name starts with a letter or underscore, not a digit.
  2. It can contain letters, digits and underscores only.
  3. Spaces and symbols such as hyphens are not allowed.
  4. A Python keyword cannot be used as a variable name.
  5. Names are case-sensitive.
  6. Use meaningful names such as total_marks rather than unclear names.
NameValidityReason
student_nameValidLetters and underscore
mark2ValidDigit appears after first character
_totalValidMay begin with underscore
2marksInvalidBegins with a digit
total-marksInvalidHyphen is an operator
classInvalidReserved keyword
12(a)(ii)

Python program to swap two variables

8 marks

Python supports simultaneous assignment, so a temporary variable is not required.

swap.py
a = input("Enter first value: ")
b = input("Enter second value: ")

print("Before swapping:", a, b)
a, b = b, a
print("After swapping:", a, b)

Example: if inputs are 12 and 30, after swapping the values are 30 and 12. Inputs are strings here; use int(input(...)) for integer-only values.

12(b)(i)

Operator precedence and order

8 marks

Precedence determines which operator is evaluated first when an expression contains operators of different priorities. Parentheses can be used to make the intended order explicit.

Higher → lowerOperators / examples
1Parentheses/grouping: ()
2Exponentiation: **
3Unary plus/minus and bitwise NOT: +x, -x, ~x
4Multiplication, division, floor division, remainder: * / // %
5Addition and subtraction: + -
6Shifts: << >>
7–9Bitwise AND &, XOR ^, OR |
10Comparisons, membership and identity: < <= == != in is
11Logical NOT: not
12Logical AND: and
13Logical OR: or

Example 1: 2 + 3 * 4 = 14, because multiplication comes before addition. Example 2: (2 + 3) * 4 = 20, because parentheses are evaluated first.

Associativity: operators of equal precedence generally group left to right, but exponentiation groups right to left: 2 ** 3 ** 2 = 2 ** (3 ** 2) = 512. Unary signs and exponentiation have a special relationship, so use parentheses when clarity matters.

12(b)(ii)

Python program to test a leap year

8 marks

A year is a leap year when it is divisible by 400, or divisible by 4 but not divisible by 100.

leap_year.py
year = int(input("Enter a year: "))

if year % 400 == 0:
    print(year, "is a leap year")
elif year % 100 == 0:
    print(year, "is not a leap year")
elif year % 4 == 0:
    print(year, "is a leap year")
else:
    print(year, "is not a leap year")

Test: 2000 is a leap year; 1900 is not; 2024 is a leap year; 2023 is not.

Section 04 · Question 13

Strings, arrays & searching

String module explanation and two common programs.

13(a)(i)

Explain the Python string module

8 marks

The standard-library string module supplies useful string constants and a few helper functions. It is imported using import string.

MemberPurpose
string.ascii_lowercaseLowercase English letters a-z
string.ascii_uppercaseUppercase English letters A-Z
string.ascii_lettersLowercase and uppercase ASCII letters
string.digitsDecimal digits 0-9
string.hexdigitsHexadecimal digit characters
string.punctuationASCII punctuation characters
string.whitespaceWhitespace characters recognised by the module
string.capwords(text)Splits words, capitalises them and joins them with spaces
Example
import string

print(string.ascii_lowercase)
print(string.digits)
print(string.punctuation)
print(string.capwords("problem solving with python"))
# Problem Solving With Python

Note: methods such as upper(), lower(), split() and replace() are methods of string objects, rather than constants in the string module.

13(a)(ii)

Find sum and average of an array of numbers

8 marks

This solution uses a Python list to store the values; it calculates the total and then divides by the number of values.

sum_average.py
n = int(input("How many numbers? "))

if n <= 0:
    print("Enter a positive count")
else:
    numbers = []
    for i in range(n):
        value = float(input(f"Enter number {i + 1}: "))
        numbers.append(value)

    total = sum(numbers)
    average = total / len(numbers)
    print("Numbers:", numbers)
    print("Sum =", total)
    print("Average =", average)

Formula: Sum = x₁ + x₂ + … + xₙ; average = sum / n. Checking that n > 0 prevents division by zero.

13(b)

Sequential (linear) search of a list

16 marks

Definition: Sequential search examines list elements one by one from the beginning. It stops when the key is found or when all elements have been checked. It works on unsorted as well as sorted lists.

Algorithm

  1. Read the list and search key.
  2. Set index i = 0.
  3. While i is less than the list length, compare the element at index i with the key.
  4. If equal, report the position and stop.
  5. Otherwise increment i and continue.
  6. If the end is reached, report that the key was not found.
linear_search.py
def linear_search(items, key):
    for index, value in enumerate(items):
        if value == key:
            return index  # zero-based index
    return -1

values = [12, 7, 25, 4, 18]
key = int(input("Enter the value to search: "))
position = linear_search(values, key)

if position != -1:
    print("Found at position", position + 1)
else:
    print("Value not found")

Example: For [12, 7, 25, 4, 18], key 25 is found at position 3 (human counting starts at 1). If the key is absent, the function returns -1.

PerformanceResult
Best caseO(1) — key is first
Worst caseO(n) — key is last or absent
Extra spaceO(1) for this iterative implementation
Section 05 · Question 14

Lists and electricity billing

Long-form list operations and a billing program based on the given table.

14(a)

Lists, list operations and list slices

16 marks

List: a list is an ordered, mutable sequence that can store elements of different data types. It is written using square brackets, for example marks = [78, 85, 92]. List indexes start at 0, and negative indexes count from the end.

Common list operations

OperationExampleMeaning
Access / updatea[0], a[1] = 8Read or replace an element
Appenda.append(4)Add one item at the end
Extenda.extend([5, 6])Add items from an iterable
Inserta.insert(1, 9)Insert at a specific index
Removea.remove(9)Remove first matching value
Popa.pop()Remove and return an item; default is last
Deletedel a[0]Delete an item or slice
Sort / reversea.sort(), a.reverse()Sort in place / reverse in place
Search helpersa.index(4), a.count(4)Find first index / count matches
Combine / repeata + b, a * 2Concatenate / repeat a list
Length / membershiplen(a), 4 in aGet item count / test presence

List slicing: list[start:stop:step] extracts a subsequence. The start index is included, but the stop index is excluded. Omitting start or stop uses a default boundary.

List and slice examples
a = [10, 20, 30, 40, 50, 60]
print(a[0])       # 10
print(a[-1])      # 60
print(a[1:4])     # [20, 30, 40]
print(a[:3])      # [10, 20, 30]
print(a[3:])      # [40, 50, 60]
print(a[::2])     # [10, 30, 50]
print(a[::-1])    # [60, 50, 40, 30, 20, 10]

copy_of_a = a[:]  # shallow clone

Important: lists are mutable, so operations such as item assignment, append() and remove() change the list itself. A slice generally creates a new list (a shallow copy), while a slice assignment can modify the original list.

14(b)

Electricity bill based on units and consumer type

16 marks

The program reads units consumed and whether the connection is domestic or commercial, then selects the corresponding price from the printed table.

Units as printed on paperDomestic priceCommercial price
Up to 200 units200 (base price)500
Units > 200 and < 50011001700
Units > 500 and < 100045007000
Important ambiguity in the source paper: the printed ranges omit exactly 500 units and exactly 1,000 units (and do not state what happens above 1,000). The code below follows the table as printed and reports those cases as unspecified rather than inventing a tariff.
electricity_bill.py
units = int(input("Enter units consumed: "))
kind = input("Connection type (domestic/commercial): ").strip().lower()

if units < 0:
    print("Units cannot be negative")
elif kind not in ("domestic", "commercial"):
    print("Enter domestic or commercial")
elif units <= 200:
    bill = 200 if kind == "domestic" else 500
    print(f"Electricity bill: {bill}")
elif 200 < units < 500:
    bill = 1100 if kind == "domestic" else 1700
    print(f"Electricity bill: {bill}")
elif 500 < units < 1000:
    bill = 4500 if kind == "domestic" else 7000
    print(f"Electricity bill: {bill}")
else:
    print("Tariff not specified for this unit count in the question paper")

Note: These are flat prices for the unit bands shown in the question, not per-unit multiplication. If your lecturer expects 500 to be included in the middle band or 1,000 in the highest band, confirm that intended boundary rule before changing the conditions.

Section 06 · Question 15

File handling and stack

File copy in chunks, text-file counting, and a modular stack implementation.

15(a)(i)

Copy a file 50 characters at a time

8 marks

Read at most 50 characters in each iteration and write that chunk to the destination until no characters remain.

copy_file.py
def copy_file(source_name, destination_name):
    with open(source_name, "r", encoding="utf-8") as source:
        with open(destination_name, "w", encoding="utf-8") as destination:
            while True:
                chunk = source.read(50)
                if chunk == "":
                    break
                destination.write(chunk)

copy_file("input.txt", "copy.txt")
print("File copied successfully")

Explanation: read(50) returns up to 50 characters. An empty string indicates end-of-file. The with statement closes both files automatically.

This character-based version is suitable for text files. For arbitrary binary files, use binary modes (rb/wb) and read chunks as bytes.

15(a)(ii)

Count lines, words and characters in a text file

8 marks

In this answer, characters include spaces and newline characters because the entire text is read as-is.

count_text.py
with open("input.txt", "r", encoding="utf-8") as file:
    text = file.read()

characters = len(text)
words = len(text.split())
lines = len(text.splitlines())

print("Lines:", lines)
print("Words:", words)
print("Characters:", characters)

Explanation: split() separates text on runs of whitespace, while splitlines() separates line breaks. For a completely empty file, both counts are zero.

If the examiner defines a blank file or a trailing newline as a line differently, state the counting convention you use.

15(b)

Implement stack operations using modules

16 marks

A stack is a Last-In, First-Out (LIFO) data structure. The main operations are push (insert at top), pop (remove the top item), peek (view the top item), and display.

Save the first program as stack_module.py and the second as main.py in the same folder.

File 1 · stack_module.py
_stack = []

def push(item):
    _stack.append(item)
    print(item, "pushed")

def pop():
    if not _stack:
        print("Stack underflow: stack is empty")
        return None
    return _stack.pop()

def peek():
    if not _stack:
        return None
    return _stack[-1]

def display():
    if not _stack:
        print("Stack is empty")
    else:
        print("Bottom → top:", _stack)

def is_empty():
    return len(_stack) == 0
File 2 · main.py
import stack_module as stack

while True:
    print("\n1.Push  2.Pop  3.Peek  4.Display  5.Exit")
    choice = input("Enter choice: ").strip()

    if choice == "1":
        item = input("Enter item: ")
        stack.push(item)
    elif choice == "2":
        item = stack.pop()
        if item is not None:
            print("Popped:", item)
    elif choice == "3":
        item = stack.peek()
        if item is None:
            print("Stack is empty")
        else:
            print("Top item:", item)
    elif choice == "4":
        stack.display()
    elif choice == "5":
        print("Program ended")
        break
    else:
        print("Invalid choice")

Working: the main program imports the module and calls its functions. The stack module stores stack data and implements each operation. Popping an empty stack is called stack underflow, which is handled here with a message.

Section 07 · Active recall

Quick revision quiz

Five fast checks to see what stuck. Try before revealing your score.

1. Which structure follows Last-In, First-Out?

2. What is the output of 2 + 3 * 4?

3. Which operation creates a shallow list copy?

4. Which is the correct leap-year rule?

5. What does an empty string returned by file.read(50) indicate?

Exam-writing tip

For an 8- or 16-mark programming answer, aim to write the definition or logic, a short algorithm / explanation, the complete program, and one sample result where appropriate. Use indentation consistently and mention assumptions if the question leaves a rule unspecified.

Prepared from the uploaded GE3151 question paper (Question Paper Code 30198, April/May 2023). Some wording, notably the strategy list and the electricity-tariff boundaries, may depend on your prescribed class notes.

GE3151 · Problem Solving and Python Programming · Revision page Made for focused practice ✦

Comments

Popular posts from this blog

index.html

Python #1 Fundamentals

#Python YT Videos for Jamal Engineering Students