FAC1003 — Programming Revision Questions

Source style: Adapted from the Revision (Part B) slides. Each question gives a real-world scenario, specifies required sub-functions (void/non-void, pass-by-value, recursion, pointers), and expects a complete C++ program with example output.


Section A — Modular Functions (Non-Void + Void)

Q1 — Electricity Bill Calculator

A utility company wants a C++ program to calculate residential electricity bills. The company charges:

Usage (kWh) Rate (RM/kWh)
First 200 kWh 0.218
Next 100 kWh (201–300) 0.334
Above 300 kWh 0.516

The company also applies a fixed monthly charge of RM5.00 for all customers. Customers who use more than 600 kWh receive an additional 5% surcharge on the total bill (excluding the fixed charge).

Task:

Write a complete C++ program that does the following:

  1. Ask the user to enter:

    • Customer name
    • Total electricity usage in kWh (as a double)
  2. Use a non-void function named calculateCharge(double usage) that:

    • Returns the total consumption charge based on the tiered rates above
    • (The fixed charge and surcharge are applied separately — not inside this function)
  3. Use a non-void function named calculateSurcharge(double charge) that:

    • Returns 5% of the charge if usage exceeds 600 kWh
    • Returns 0 otherwise
  4. Use a void function named displayBill(string name, double usage, double charge, double surcharge) that:

    • Displays the customer name
    • Shows a breakdown of usage, tiered charge, fixed charge (RM5.00), surcharge, and total amount
    • Formats all monetary values to 2 decimal places

All values are passed by value.

Example output:

Enter customer name: Aisha
Enter total electricity usage (kWh): 450

--- Electricity Bill ---
Customer Name: Aisha
Usage: 450.00 kWh
Consumption Charge: RM140.20
Fixed Charge: RM5.00
Surcharge: RM0.00 (usage ≤ 600 kWh)
Total Amount: RM145.20

Example output (with surcharge):

Enter customer name: Beng
Enter total electricity usage (kWh): 720

--- Electricity Bill ---
Customer Name: Beng
Usage: 720.00 kWh
Consumption Charge: RM272.72
Fixed Charge: RM5.00
Surcharge: RM13.64 (5% of consumption charge)
Total Amount: RM291.36

Q2 — Loan Repayment Calculator

A bank offers personal loans with the following terms:

  • Loan amounts between RM1,000 and RM50,000
  • Annual interest rate: 4.5% for loans ≤ RM10,000, 3.9% for loans > RM10,000
  • Loan tenure: 6, 12, 24, or 36 months

The monthly payment is calculated using the formula:

monthlyPayment = (loanAmount + totalInterest) / tenureMonths

where totalInterest = loanAmount × annualRate × (tenureMonths / 12).

Write a complete C++ program that does the following:

  1. Ask the user to enter:

    • Customer name
    • Loan amount (RM)
    • Loan tenure in months (6, 12, 24, or 36 — the program MUST validate this)
  2. Use a non-void function named getInterestRate(double amount) that:

    • Returns the applicable annual interest rate based on loan amount
    • Returns -1.0 if the loan amount is outside the valid range
  3. Use a non-void function named calculateMonthlyPayment(double amount, double rate, int tenure) that:

    • Computes and returns the monthly payment using the formula above
  4. Use a void function named displayLoanSummary(string name, double amount, int tenure, double rate, double monthly) that:

    • Displays a complete loan summary table
    • Shows: loan amount, annual rate, tenure, total interest paid, total repayment, and monthly payment
    • Formats all monetary values to 2 decimal places

Validation rules:

  • If the user enters an invalid loan amount (< 1000 or > 50000), the program should display "Invalid loan amount. Must be between RM1,000 and RM50,000." and exit.
  • If the user enters an invalid tenure (not 6, 12, 24, or 36), the program should display "Invalid tenure. Must be 6, 12, 24, or 36 months." and keep asking until a valid value is entered.

Example output:

Enter customer name: Chan
Enter loan amount (RM): 15000
Enter loan tenure (months): 24

--- Loan Summary ---
Customer: Chan
Loan Amount: RM15000.00
Annual Interest Rate: 3.90%
Tenure: 24 months
Total Interest: RM1170.00
Total Repayment: RM16170.00
Monthly Payment: RM673.75

Section B — Recursion

Q3 — Digit Sum & Digital Root

Write a C++ program that processes a positive integer entered by the user using recursion. The program has two tasks:

Task A — Sum of Digits: Compute the sum of all digits of the number recursively. Task B — Digital Root: Keep summing the digits until a single digit remains (the digital root).

For example:

  • Number: 4723
  • Digit sum: 4 + 7 + 2 + 3 = 16
  • Digital root: 1 + 6 = 7

Requirements:

  1. Ask the user to enter a positive integer (no validation needed — assume valid input).

  2. Use a recursive non-void function int sumOfDigits(int n) that:

    • Returns the sum of all digits of n
    • Base case: if n == 0, return 0
    • Recursive case: return (n % 10) + sumOfDigits(n / 10)
  3. Use a recursive non-void function int digitalRoot(int n) that:

    • If n < 10, return n
    • Otherwise, return digitalRoot(sumOfDigits(n))
  4. Use a void function displayDigitAnalysis(int original) that:

    • Displays the number entered
    • Shows the step-by-step digit sum calculation: each digit separated by +
    • Shows the sum of digits
    • Shows the digital root with its step-by-step reduction

Example output:

Enter a positive integer: 4723

--- Digit Analysis ---
Number: 4723
Digit Sum: 4 + 7 + 2 + 3 = 16
Digital Root: 16 → 1 + 6 = 7
Final Digital Root: 7

Example output (single digit):

Enter a positive integer: 9

--- Digit Analysis ---
Number: 9
Digit Sum: 9 = 9
Digital Root: 9 (already a single digit)
Final Digital Root: 9

Q4 — Recursive Prime Factorisation

Write a C++ program that recursively decomposes a positive integer into its prime factors.

Prime factorisation is the process of breaking a number into the product of its prime factors:

  • 12 = 2 × 2 × 3
  • 30 = 2 × 3 × 5
  • 100 = 2 × 2 × 5 × 5
  • 97 = 97 (prime — no factorisation)

Requirements:

  1. Ask the user to enter a positive integer greater than 1. If the user enters a number ≤ 1, display "Please enter a number greater than 1." and ask again until valid input is given.

  2. Use a recursive non-void function bool isPrime(int n, int divisor = 2) that:

    • Returns true if n is prime, false otherwise
    • Base cases: if n <= 2, return n == 2; if n % divisor == 0, return false
    • Recursive case: return isPrime(n, divisor + 1)
    • Only check divisors up to sqrt(n) — stop recursion when divisor * divisor > n
  3. Use a recursive void function void factorise(int n, bool first = true) that:

    • If n == 1, return (done)
    • If n is prime, print n and return
    • Otherwise, find the smallest divisor d of n (starting from 2)
    • Print d, then recursively call factorise(n / d, false)
    • Print × between factors — the first parameter controls whether a × is printed before the factor
  4. Use a void function void displayFactorisation(int n) that:

    • Calls factorise(n) to print the prime factors
    • Prints n = followed by the factorisation
    • If the number is prime, prints n = n (prime) instead

Example output:

Enter a positive integer (> 1): 84

84 = 2 × 2 × 3 × 7

Example output (prime):

Enter a positive integer (> 1): 97

97 = 97 (prime)

Example output (invalid → retry):

Enter a positive integer (> 1): 1
Please enter a number greater than 1.
Enter a positive integer (> 1): -5
Please enter a number greater than 1.
Enter a positive integer (> 1): 60

60 = 2 × 2 × 3 × 5

Section C — Pointers & Dynamic 2D Arrays

Q5 — Temperature Anomaly Tracker

A climate research centre records daily temperature anomalies across multiple weather stations. Each station takes measurements at different times of day. Write a C++ program that processes this data using dynamic 2D arrays and pointer notation only.

Requirements:

  1. The program shall first prompt the user to enter:

    • The number of weather stations
    • The number of daily readings (each station has the same number of readings)
  2. Based on these values, dynamically allocate a 2D array of doubles. The memory MUST be allocated and accessed strictly using pointer notation (i.e., *(*(arr + i) + j), NOT arr[i][j]).

  3. The program shall then read the readings (temperature anomalies in °C) for each station across all daily readings.

  4. For each station, compute:

    • Mean temperature anomaly
    • Maximum anomaly (highest positive value)
    • Minimum anomaly (lowest negative value — or 0 if all readings are positive)
    • Range (max - min)
  5. Classify each station based on its mean anomaly:

    Mean Anomaly (°C) Classification
    > +2.0 Extreme Warming
    +0.5 to +2.0 Moderate Warming
    -0.5 to +0.5 Stable
    -2.0 to -0.5 Moderate Cooling
    < -2.0 Extreme Cooling
  6. Use a void function void displayStationReport(double* anomalies, int numReadings, int stationIndex) that:

    • Takes a pointer to a single row of the 2D array (one station's data)
    • Computes and displays the mean, max, min, range, and classification for that station
  7. Memory cleanup: Deallocate the 2D array after processing.

Hint: To allocate a 2D array using pointers:

double** data = new double*[numStations];
for (int i = 0; i < numStations; i++)
    data[i] = new double[numReadings];

But all access must use pointer arithmetic: *(*(data + i) + j).

Example output:

Enter number of weather stations: 3
Enter number of daily readings: 4

Station 1, Reading 1: 1.2
Station 1, Reading 2: 2.5
Station 1, Reading 3: 3.1
Station 1, Reading 4: 2.8
Station 2, Reading 1: -0.5
Station 2, Reading 2: -1.2
Station 2, Reading 3: 0.3
Station 2, Reading 4: -0.8
Station 3, Reading 1: 3.5
Station 3, Reading 2: 4.2
Station 3, Reading 3: 3.9
Station 3, Reading 4: 4.8

--- Station Report ---
Station 1: Mean = 2.40°C | Max = 3.10°C | Min = 1.20°C | Range = 1.90°C | Moderate Warming
Station 2: Mean = -0.55°C | Max = 0.30°C | Min = -1.20°C | Range = 1.50°C | Moderate Cooling
Station 3: Mean = 4.10°C | Max = 4.80°C | Min = 3.50°C | Range = 1.30°C | Extreme Warming

Q6 — Sparse Matrix Compression (Dynamic Pointer Structure)

[!warning] Hard This question combines dynamic memory allocation, pointers, and structured programming. It is more difficult than a typical exam question — treat it as a stretch exercise.

A sparse matrix is a matrix where most elements are zero. Instead of storing all the zeros, we can use a compressed representation: store only the non-zero values along with their row and column positions.

Write a C++ program that converts a regular 2D matrix into a compressed sparse representation using dynamic arrays and pointer notation.

Requirements:

  1. Ask the user to enter the dimensions of a matrix:

    • Number of rows
    • Number of columns
  2. Dynamically allocate a 2D integer array (int**) and read its elements from the user.

  3. After reading the full matrix, count the number of non-zero elements.

  4. Dynamically allocate three 1D arrays using pointers:

    • int* values — stores the non-zero values
    • int* rowIndices — stores the row index of each non-zero value
    • int* colIndices — stores the column index of each non-zero value

    The size of each array should be exactly the number of non-zero elements.

  5. Use a void function void compressMatrix(int** matrix, int rows, int cols, int*& values, int*& rowIndices, int*& colIndices, int& nonZeroCount) that:

    • Scans the matrix row by row
    • For each non-zero element, appends its value, row index, and column index to the respective dynamic arrays
    • The function parameters values, rowIndices, colIndices are passed by reference (they will be allocated inside the function)
  6. Use a void function void displayMatrix(int** matrix, int rows, int cols) that:

    • Displays the full matrix in grid format
  7. Use a void function void displayCompressed(int* values, int* rowIndices, int* colIndices, int nonZeroCount) that:

    • Displays the compressed representation as a table
  8. Use a void function void reconstructAndDisplay(int* values, int* rowIndices, int* colIndices, int nonZeroCount, int rows, int cols) that:

    • Reconstructs the matrix from the compressed representation
    • Displays it — it should match the original matrix exactly
  9. Memory cleanup: Deallocate ALL dynamically allocated memory (the original 2D array AND the three compressed arrays).

Example output:

Enter number of rows: 3
Enter number of columns: 4

Row 0:
  Col 0: 0
  Col 1: 0
  Col 2: 5
  Col 3: 0
Row 1:
  Col 0: 0
  Col 1: 0
  Col 2: 0
  Col 3: 0
Row 2:
  Col 0: 3
  Col 1: 0
  Col 2: 0
  Col 3: 8

Original Matrix:
  0  0  5  0
  0  0  0  0
  3  0  0  8

Compressed Representation (Non-zero elements: 3):
Value   Row   Col
  5      0     2
  3      2     0
  8      2     3

Reconstructed Matrix:
  0  0  5  0
  0  0  0  0
  3  0  0  8

Matrices match!

Example output (all zeros):

Enter number of rows: 2
Enter number of columns: 2

Row 0:
  Col 0: 0
  Col 1: 0
Row 1:
  Col 0: 0
  Col 1: 0

Original Matrix:
  0  0
  0  0

No non-zero elements found. Matrix is entirely zero.

Related