Loading....
|
Press & Hold to Drag Around |
|||
|
Click Here to Close |
|||
Question 1 Report
An array Data[1:20] contains 20 integers that may include duplicate values. A program is needed to create a new array Unique that contains only the distinct values from Data.
(a) Write pseudocode for this algorithm. Your solution should count the number of unique values found. [6]
(b) Trace the first 5 elements of the algorithm with the input array: [4, 7, 4, 2, 7, ...] [3]
| Data element | Already in Unique? | Action | Unique array | UniqueCount |
|---|---|---|---|---|
| 4 | ||||
| 7 | ||||
| 4 | ||||
| 2 | ||||
| 7 |
(c) State the worst-case and best-case values for UniqueCount and explain when each occurs. [1]
(a) The algorithm must iterate through every element in Data[1:20] and check whether it already appears in a growing Unique array. If the element has not been seen before, it is added to Unique and the counter is incremented. [6]
DECLARE Data : ARRAY[1:20] OF INTEGER
DECLARE Unique : ARRAY[1:20] OF INTEGER
DECLARE UniqueCount : INTEGER
DECLARE i : INTEGER
DECLARE j : INTEGER
DECLARE IsDuplicate : BOOLEAN
UniqueCount ← 0
FOR i ← 1 TO 20
IsDuplicate ← FALSE
FOR j ← 1 TO UniqueCount
IF Data[i] = Unique[j] THEN
IsDuplicate ← TRUE
ENDIF
NEXT j
IF IsDuplicate = FALSE THEN
UniqueCount ← UniqueCount + 1
Unique[UniqueCount] ← Data[i]
ENDIF
NEXT i
OUTPUT "Number of unique values: ", UniqueCountThe outer loop visits each element of Data in turn [1]. The inner loop scans all values already stored in Unique to test for a duplicate [1]. The flag IsDuplicate records whether a match was found [1]. Only when no match is found is the value appended and the counter advanced [1]. Initialising UniqueCount to 0 ensures the inner loop does not execute on the first element, so the first value is always added [1].
(b) Trace for the first 5 elements of the input array [4, 7, 4, 2, 7, ...]: [3]
| Data element | Already in Unique? | Action | Unique array | UniqueCount |
|---|---|---|---|---|
| 4 | No (Unique is empty) | Add | [4] | 1 |
| 7 | No | Add | [4, 7] | 2 |
| 4 | Yes (matches Unique[1]) | Skip | [4, 7] | 2 |
| 2 | No | Add | [4, 7, 2] | 3 |
| 7 | Yes (matches Unique[2]) | Skip | [4, 7, 2] | 3 |
The first two elements are new, so both are added [1]. When 4 is encountered again it matches Unique[1], so it is skipped [1]. The value 2 is new, but the second 7 matches Unique[2] [1].
(c) Best case: UniqueCount = 1, which occurs when all 20 elements hold the same value. Worst case: UniqueCount = 20, which occurs when every element is different. [1]
(a) The algorithm must iterate through every element in Data[1:20] and check whether it already appears in a growing Unique array. If the element has not been seen before, it is added to Unique and the counter is incremented. [6]
DECLARE Data : ARRAY[1:20] OF INTEGER
DECLARE Unique : ARRAY[1:20] OF INTEGER
DECLARE UniqueCount : INTEGER
DECLARE i : INTEGER
DECLARE j : INTEGER
DECLARE IsDuplicate : BOOLEAN
UniqueCount ← 0
FOR i ← 1 TO 20
IsDuplicate ← FALSE
FOR j ← 1 TO UniqueCount
IF Data[i] = Unique[j] THEN
IsDuplicate ← TRUE
ENDIF
NEXT j
IF IsDuplicate = FALSE THEN
UniqueCount ← UniqueCount + 1
Unique[UniqueCount] ← Data[i]
ENDIF
NEXT i
OUTPUT "Number of unique values: ", UniqueCountThe outer loop visits each element of Data in turn [1]. The inner loop scans all values already stored in Unique to test for a duplicate [1]. The flag IsDuplicate records whether a match was found [1]. Only when no match is found is the value appended and the counter advanced [1]. Initialising UniqueCount to 0 ensures the inner loop does not execute on the first element, so the first value is always added [1].
(b) Trace for the first 5 elements of the input array [4, 7, 4, 2, 7, ...]: [3]
| Data element | Already in Unique? | Action | Unique array | UniqueCount |
|---|---|---|---|---|
| 4 | No (Unique is empty) | Add | [4] | 1 |
| 7 | No | Add | [4, 7] | 2 |
| 4 | Yes (matches Unique[1]) | Skip | [4, 7] | 2 |
| 2 | No | Add | [4, 7, 2] | 3 |
| 7 | Yes (matches Unique[2]) | Skip | [4, 7, 2] | 3 |
The first two elements are new, so both are added [1]. When 4 is encountered again it matches Unique[1], so it is skipped [1]. The value 2 is new, but the second 7 matches Unique[2] [1].
(c) Best case: UniqueCount = 1, which occurs when all 20 elements hold the same value. Worst case: UniqueCount = 20, which occurs when every element is different. [1]
Question 2 Report
A 2D array stores the number of items sold by 3 shops over 4 weeks.
DECLARE Sales : ARRAY[1:3, 1:4] OF INTEGER
The array contents are:
| Week 1 | Week 2 | Week 3 | Week 4 | |
|---|---|---|---|---|
| Shop 1 | 120 | 150 | 130 | 140 |
| Shop 2 | 200 | 180 | 210 | 190 |
| Shop 3 | 90 | 110 | 100 | 95 |
The following pseudocode calculates the total sales for each shop.
FOR Shop <- 1 TO 3
DECLARE ShopTotal : INTEGER
ShopTotal <- 0
FOR Week <- 1 TO 4
ShopTotal <- ShopTotal + Sales[Shop, Week]
NEXT Week
OUTPUT "Shop ", Shop, " total: ", ShopTotal
NEXT Shop
(a) Complete the trace table showing ShopTotal at the end of each inner loop iteration for Shop 1 only. [2]
| Week | Sales[1, Week] | ShopTotal |
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 |
(b) State the three lines of output produced by the program. [3]
(c) Write pseudocode to find and output the highest single weekly sales figure across all shops and weeks. [1]
(a) Trace table for Shop 1 (the inner loop with Shop = 1): [2]
| Week | Sales[1, Week] | ShopTotal |
|---|---|---|
| 1 | 120 | 120 |
| 2 | 150 | 270 |
| 3 | 130 | 400 |
| 4 | 140 | 540 |
[1] for correct Sales values from the table, [1] for correct running totals (each row adds the Sales value to the previous ShopTotal).
ShopTotal is reset to 0 before each shop's inner loop begins. For Shop 1: 0+120=120, 120+150=270, 270+130=400, 400+140=540.
(b) The three lines of output: [3]
Shop 1 total: 540
Shop 2 total: 780
Shop 3 total: 395[1] for Shop 1 = 10+20+15 is wrong - wait, for the OUTPUT, Shop 1 uses the Sales array: 120+150+130+140 = 540. [1] for Shop 2 = 200+180+210+190 = 780. [1] for Shop 3 = 90+110+100+95 = 395.
(c) Pseudocode to find the highest single weekly sales figure: [1]
DECLARE Highest : INTEGER
Highest <- Sales[1, 1]
FOR Shop <- 1 TO 3
FOR Week <- 1 TO 4
IF Sales[Shop, Week] > Highest
THEN
Highest <- Sales[Shop, Week]
ENDIF
NEXT Week
NEXT Shop
OUTPUT "Highest: ", HighestThe algorithm initialises Highest to the first element (Sales[1,1] = 120), then uses nested loops to check every element in the 2D array. Whenever a value exceeds the current Highest, it replaces it. The expected answer is 210 (Shop 2, Week 3).
(a) Trace table for Shop 1 (the inner loop with Shop = 1): [2]
| Week | Sales[1, Week] | ShopTotal |
|---|---|---|
| 1 | 120 | 120 |
| 2 | 150 | 270 |
| 3 | 130 | 400 |
| 4 | 140 | 540 |
[1] for correct Sales values from the table, [1] for correct running totals (each row adds the Sales value to the previous ShopTotal).
ShopTotal is reset to 0 before each shop's inner loop begins. For Shop 1: 0+120=120, 120+150=270, 270+130=400, 400+140=540.
(b) The three lines of output: [3]
Shop 1 total: 540
Shop 2 total: 780
Shop 3 total: 395[1] for Shop 1 = 10+20+15 is wrong - wait, for the OUTPUT, Shop 1 uses the Sales array: 120+150+130+140 = 540. [1] for Shop 2 = 200+180+210+190 = 780. [1] for Shop 3 = 90+110+100+95 = 395.
(c) Pseudocode to find the highest single weekly sales figure: [1]
DECLARE Highest : INTEGER
Highest <- Sales[1, 1]
FOR Shop <- 1 TO 3
FOR Week <- 1 TO 4
IF Sales[Shop, Week] > Highest
THEN
Highest <- Sales[Shop, Week]
ENDIF
NEXT Week
NEXT Shop
OUTPUT "Highest: ", HighestThe algorithm initialises Highest to the first element (Sales[1,1] = 120), then uses nested loops to check every element in the 2D array. Whenever a value exceeds the current Highest, it replaces it. The expected answer is 210 (Shop 2, Week 3).
Question 3 Report
The following flowchart represents an algorithm that processes a positive integer.
(a) Trace through the flowchart for N = 16, showing the value of N and Count at each step. [4]
(b) State the output when N = 16. [1]
(c) State what this algorithm calculates for any given positive integer input. [2]
(a) The flowchart repeatedly divides N by 2 (integer division) and increments Count, stopping when N is no longer greater than 1:
| Iteration | N (start) | N > 1? | N DIV 2 | Count |
|---|---|---|---|---|
| Initial | 16 | - | - | 0 |
| 1 | 16 | TRUE | 8 | 1 |
| 2 | 8 | TRUE | 4 | 2 |
| 3 | 4 | TRUE | 2 | 3 |
| 4 | 2 | TRUE | 1 | 4 |
| Check | 1 | FALSE | - | 4 |
Each iteration halves N and adds 1 to Count. After 4 iterations, N reaches 1 and the loop exits. [4]
(b) The output is 4. [1]
(c) The algorithm calculates how many times N can be halved (using integer division by 2) before reaching 1. [1] For inputs that are exact powers of 2, this gives the exponent, equivalent to log base 2 of N. For example, 16 = 24, so Count = 4. For non-powers of 2, integer division still counts the halvings, but the result is the floor of log2(N). [1] [2]
(a) The flowchart repeatedly divides N by 2 (integer division) and increments Count, stopping when N is no longer greater than 1:
| Iteration | N (start) | N > 1? | N DIV 2 | Count |
|---|---|---|---|---|
| Initial | 16 | - | - | 0 |
| 1 | 16 | TRUE | 8 | 1 |
| 2 | 8 | TRUE | 4 | 2 |
| 3 | 4 | TRUE | 2 | 3 |
| 4 | 2 | TRUE | 1 | 4 |
| Check | 1 | FALSE | - | 4 |
Each iteration halves N and adds 1 to Count. After 4 iterations, N reaches 1 and the loop exits. [4]
(b) The output is 4. [1]
(c) The algorithm calculates how many times N can be halved (using integer division by 2) before reaching 1. [1] For inputs that are exact powers of 2, this gives the exponent, equivalent to log base 2 of N. For example, 16 = 24, so Count = 4. For non-powers of 2, integer division still counts the halvings, but the result is the floor of log2(N). [1] [2]
Question 4 Report
A warehouse uses a database table called STOCK to track inventory.
| ItemCode | Description | Supplier | QuantityInStock | ReorderLevel | UnitCost |
|---|---|---|---|---|---|
| WH001 | Steel Bolt M8 | MetalCo | 500 | 100 | 0.15 |
| WH002 | Rubber Washer | SealParts | 80 | 200 | 0.08 |
| WH003 | Copper Wire 2m | MetalCo | 250 | 50 | 1.20 |
| WH004 | Plastic Clip | SealParts | 150 | 100 | 0.05 |
| WH005 | Aluminium Sheet | MetalCo | 30 | 25 | 4.50 |
(a) Write an SQL query to find all items where QuantityInStock is below the ReorderLevel. [2]
(b) Write an SQL INSERT statement to add a new item with code 'WH006', description 'Nylon Strap', supplier 'SealParts', quantity 400, reorder level 150, and unit cost 0.30. [3]
(c) Write an SQL query to find the total value of stock (QuantityInStock multiplied by UnitCost) for each supplier. [3]
(d) State two fields where a range check should be applied and describe the valid range for each. [2]
(e) Write a SQL query to count the total number of records in the table. [2]
(f) Write a SQL query to find the average value of a numeric field for each category, showing only categories with more than 2 records. [3]
(g) Write a SQL query to update the status of all records that match a given condition. [2]
(h) Describe two advantages of using a database rather than a flat file for this data. [2]
(i) Write a SQL query to display all records sorted in descending order by a numeric field, limited to the first 5 results. [1]
(a) SQL query for items below reorder level: [2]
SELECT *
FROM STOCK
WHERE QuantityInStock < ReorderLevelThis compares two fields within the same record. From the data, only WH002 (Rubber Washer: quantity 80, reorder level 200) satisfies the condition where 80 < 200.
(b) SQL INSERT statement for a new item: [3]
INSERT INTO STOCK (ItemCode, Description, Supplier,
QuantityInStock, ReorderLevel, UnitCost)
VALUES ('WH006', 'Nylon Strap', 'SealParts',
400, 150, 0.30)All six values must be provided in the correct order matching the field list. String values are enclosed in single quotes; numeric values are written directly.
(c) SQL query for total stock value per supplier: [3]
SELECT Supplier, SUM(QuantityInStock * UnitCost)
FROM STOCK
GROUP BY SupplierThe expression QuantityInStock * UnitCost calculates the value for each item, and SUM totals these across each supplier group.
| Supplier | Total Value |
|---|---|
| MetalCo | 510.00 |
| SealParts | 13.90 |
Working:
(d) Two fields where a range check should be applied: [2]
(e) SQL query to count total records: [2]
SELECT COUNT(*)
FROM STOCKCOUNT(*) counts all rows in the table regardless of any NULL values. This would return 5 for the given data.
(f) SQL query for average per category with a minimum group size: [3]
SELECT Supplier, AVG(UnitCost)
FROM STOCK
GROUP BY Supplier
HAVING COUNT(*) > 2GROUP BY groups records by Supplier, AVG calculates the mean UnitCost within each group, and HAVING filters to show only groups with more than 2 records. In this data, only MetalCo (3 items) would appear; SealParts (2 items) would be excluded.
(g) SQL query to update records matching a condition: [2]
UPDATE STOCK
SET QuantityInStock = 0
WHERE QuantityInStock < ReorderLevelThe UPDATE statement modifies existing records. SET specifies the new value, and WHERE determines which records are affected. Without a WHERE clause, all records would be updated.
(h) Two advantages of using a database over a flat file: [2]
(i) SQL query for top 5 results sorted descending: [1]
SELECT *
FROM STOCK
ORDER BY UnitCost DESC
LIMIT 5ORDER BY UnitCost DESC sorts from highest to lowest cost. LIMIT 5 restricts the output to the first 5 records. This is useful for finding the most expensive items.
(a) SQL query for items below reorder level: [2]
SELECT *
FROM STOCK
WHERE QuantityInStock < ReorderLevelThis compares two fields within the same record. From the data, only WH002 (Rubber Washer: quantity 80, reorder level 200) satisfies the condition where 80 < 200.
(b) SQL INSERT statement for a new item: [3]
INSERT INTO STOCK (ItemCode, Description, Supplier,
QuantityInStock, ReorderLevel, UnitCost)
VALUES ('WH006', 'Nylon Strap', 'SealParts',
400, 150, 0.30)All six values must be provided in the correct order matching the field list. String values are enclosed in single quotes; numeric values are written directly.
(c) SQL query for total stock value per supplier: [3]
SELECT Supplier, SUM(QuantityInStock * UnitCost)
FROM STOCK
GROUP BY SupplierThe expression QuantityInStock * UnitCost calculates the value for each item, and SUM totals these across each supplier group.
| Supplier | Total Value |
|---|---|
| MetalCo | 510.00 |
| SealParts | 13.90 |
Working:
(d) Two fields where a range check should be applied: [2]
(e) SQL query to count total records: [2]
SELECT COUNT(*)
FROM STOCKCOUNT(*) counts all rows in the table regardless of any NULL values. This would return 5 for the given data.
(f) SQL query for average per category with a minimum group size: [3]
SELECT Supplier, AVG(UnitCost)
FROM STOCK
GROUP BY Supplier
HAVING COUNT(*) > 2GROUP BY groups records by Supplier, AVG calculates the mean UnitCost within each group, and HAVING filters to show only groups with more than 2 records. In this data, only MetalCo (3 items) would appear; SealParts (2 items) would be excluded.
(g) SQL query to update records matching a condition: [2]
UPDATE STOCK
SET QuantityInStock = 0
WHERE QuantityInStock < ReorderLevelThe UPDATE statement modifies existing records. SET specifies the new value, and WHERE determines which records are affected. Without a WHERE clause, all records would be updated.
(h) Two advantages of using a database over a flat file: [2]
(i) SQL query for top 5 results sorted descending: [1]
SELECT *
FROM STOCK
ORDER BY UnitCost DESC
LIMIT 5ORDER BY UnitCost DESC sorts from highest to lowest cost. LIMIT 5 restricts the output to the first 5 records. This is useful for finding the most expensive items.
Question 5 Report
An ATM (Automated Teller Machine) withdrawal process works as follows:
(a) Write pseudocode for this ATM withdrawal algorithm. Assume the correct PIN is stored in a variable StoredPIN and the account balance is in a variable Balance. [8]
(b) Complete the trace table for the following scenario: StoredPIN = "1234", Balance = 500. User enters PIN "0000", then "1234", then amount 80. [4]
| Step | PIN entered | Attempts | PIN correct? | Amount | Valid amount? | Balance | OUTPUT |
|---|---|---|---|---|---|---|---|
| 1 | |||||||
| 2 | |||||||
| 3 |
(a) The pseudocode implements an ATM withdrawal with PIN verification (up to 3 attempts) and amount validation (multiple of 10, within balance). [8]
DECLARE StoredPIN : STRING
DECLARE EnteredPIN : STRING
DECLARE Balance : REAL
DECLARE Amount : INTEGER
DECLARE Attempts : INTEGER
DECLARE Authenticated : BOOLEAN
Attempts ← 0
Authenticated ← FALSE
REPEAT
OUTPUT "Enter PIN: "
INPUT EnteredPIN
Attempts ← Attempts + 1
IF EnteredPIN = StoredPIN THEN
Authenticated ← TRUE
ELSE
OUTPUT "Incorrect PIN. ", 3 - Attempts, " attempts remaining."
ENDIF
UNTIL Authenticated = TRUE OR Attempts >= 3
IF Authenticated = FALSE THEN
OUTPUT "Card locked. Contact your bank."
ELSE
REPEAT
OUTPUT "Enter withdrawal amount (multiple of 10): "
INPUT Amount
IF Amount MOD 10 <> 0 THEN
OUTPUT "Amount must be a multiple of 10"
ELSE
IF Amount > Balance THEN
OUTPUT "Insufficient funds. Balance: ", Balance
ELSE
Balance ← Balance - Amount
OUTPUT "Dispensing ", Amount
OUTPUT "Remaining balance: ", Balance
ENDIF
ENDIF
UNTIL Amount MOD 10 = 0 AND Amount <= Balance
ENDIFThe PIN loop uses a REPEAT...UNTIL that exits when the PIN matches or 3 attempts are exhausted [1]. The attempt counter increments before the check so the limit is enforced correctly [1]. After authentication, a second loop handles the amount, rejecting non-multiples of 10 and amounts exceeding the balance [1].
(b) Trace for StoredPIN = "1234", Balance = 500, inputs: "0000", "1234", amount 80: [4]
| Step | PIN entered | Attempts | PIN correct? | Amount | Valid amount? | Balance | OUTPUT |
|---|---|---|---|---|---|---|---|
| 1 | 0000 | 1 | No | - | - | 500 | Incorrect PIN. 2 attempts remaining. |
| 2 | 1234 | 2 | Yes | - | - | 500 | (proceeds to amount entry) |
| 3 | - | 2 | Yes | 80 | Yes (80 MOD 10 = 0, 80 ≤ 500) | 420 | Dispensing 80, Remaining balance: 420 |
The first attempt fails, consuming one of three tries [1]. The second attempt succeeds, so the loop exits with Authenticated = TRUE [1]. The amount 80 passes both checks (divisible by 10, within balance), so 80 is subtracted from 500 [1].
(a) The pseudocode implements an ATM withdrawal with PIN verification (up to 3 attempts) and amount validation (multiple of 10, within balance). [8]
DECLARE StoredPIN : STRING
DECLARE EnteredPIN : STRING
DECLARE Balance : REAL
DECLARE Amount : INTEGER
DECLARE Attempts : INTEGER
DECLARE Authenticated : BOOLEAN
Attempts ← 0
Authenticated ← FALSE
REPEAT
OUTPUT "Enter PIN: "
INPUT EnteredPIN
Attempts ← Attempts + 1
IF EnteredPIN = StoredPIN THEN
Authenticated ← TRUE
ELSE
OUTPUT "Incorrect PIN. ", 3 - Attempts, " attempts remaining."
ENDIF
UNTIL Authenticated = TRUE OR Attempts >= 3
IF Authenticated = FALSE THEN
OUTPUT "Card locked. Contact your bank."
ELSE
REPEAT
OUTPUT "Enter withdrawal amount (multiple of 10): "
INPUT Amount
IF Amount MOD 10 <> 0 THEN
OUTPUT "Amount must be a multiple of 10"
ELSE
IF Amount > Balance THEN
OUTPUT "Insufficient funds. Balance: ", Balance
ELSE
Balance ← Balance - Amount
OUTPUT "Dispensing ", Amount
OUTPUT "Remaining balance: ", Balance
ENDIF
ENDIF
UNTIL Amount MOD 10 = 0 AND Amount <= Balance
ENDIFThe PIN loop uses a REPEAT...UNTIL that exits when the PIN matches or 3 attempts are exhausted [1]. The attempt counter increments before the check so the limit is enforced correctly [1]. After authentication, a second loop handles the amount, rejecting non-multiples of 10 and amounts exceeding the balance [1].
(b) Trace for StoredPIN = "1234", Balance = 500, inputs: "0000", "1234", amount 80: [4]
| Step | PIN entered | Attempts | PIN correct? | Amount | Valid amount? | Balance | OUTPUT |
|---|---|---|---|---|---|---|---|
| 1 | 0000 | 1 | No | - | - | 500 | Incorrect PIN. 2 attempts remaining. |
| 2 | 1234 | 2 | Yes | - | - | 500 | (proceeds to amount entry) |
| 3 | - | 2 | Yes | 80 | Yes (80 MOD 10 = 0, 80 ≤ 500) | 420 | Dispensing 80, Remaining balance: 420 |
The first attempt fails, consuming one of three tries [1]. The second attempt succeeds, so the loop exits with Authenticated = TRUE [1]. The amount 80 passes both checks (divisible by 10, within balance), so 80 is subtracted from 500 [1].
Question 6 Report
A class of 10 students has taken a test. Their marks are stored in an array Marks[1:10].
DECLARE Marks : ARRAY[1:10] OF INTEGER
Marks ← {72, 85, 63, 91, 45, 78, 56, 88, 70, 65}(a) Write pseudocode to calculate and output the mean (average) mark. [3]
(a) To find the mean, sum all elements using a FOR loop and divide by the count: [3]
DECLARE Total : INTEGER
DECLARE Mean : REAL
DECLARE i : INTEGER
Total ← 0
FOR i ← 1 TO 10
Total ← Total + Marks[i]
NEXT i
Mean ← Total / 10
OUTPUT "Mean mark: ", MeanThe marks are {72, 85, 63, 91, 45, 78, 56, 88, 70, 65}. Their sum is 72 + 85 + 63 + 91 + 45 + 78 + 56 + 88 + 70 + 65 = 713. The mean is 713 / 10 = 71.3. [1 mark for loop summing, 1 mark for division by 10, 1 mark for output]
(a) To find the mean, sum all elements using a FOR loop and divide by the count: [3]
DECLARE Total : INTEGER
DECLARE Mean : REAL
DECLARE i : INTEGER
Total ← 0
FOR i ← 1 TO 10
Total ← Total + Marks[i]
NEXT i
Mean ← Total / 10
OUTPUT "Mean mark: ", MeanThe marks are {72, 85, 63, 91, 45, 78, 56, 88, 70, 65}. Their sum is 72 + 85 + 63 + 91 + 45 + 78 + 56 + 88 + 70 + 65 = 713. The mean is 713 / 10 = 71.3. [1 mark for loop summing, 1 mark for division by 10, 1 mark for output]
Question 7 Report
Study the following pseudocode.
PROCEDURE SwapByValue(X : INTEGER, Y : INTEGER)
DECLARE Temp : INTEGER
Temp ← X
X ← Y
Y ← Temp
ENDPROCEDURE
PROCEDURE SwapByRef(BYREF X : INTEGER, BYREF Y : INTEGER)
DECLARE Temp : INTEGER
Temp ← X
X ← Y
Y ← Temp
ENDPROCEDURE
DECLARE A : INTEGER
DECLARE B : INTEGER
A ← 5
B ← 9
CALL SwapByValue(A, B)
OUTPUT "After SwapByValue: A=", A, " B=", B
CALL SwapByRef(A, B)
OUTPUT "After SwapByRef: A=", A, " B=", B(a) State the two lines of output. [4]
(b) Explain why SwapByValue does not change the values of A and B. [2]
(a) The key difference is that SwapByValue receives copies of A and B, while SwapByRef receives direct references to the original variables. [4]
After SwapByValue: A=5 B=9 (values unchanged because the swap operated on copies) [2]After SwapByRef: A=9 B=5 (values swapped because BYREF modifies the originals) [2](b) SwapByValue passes A and B by value, meaning the procedure receives independent copies named X and Y. [1] The swap correctly exchanges X and Y inside the procedure, but these are local copies. When the procedure ends, the copies are discarded, and the original A (still 5) and B (still 9) are unaffected. [1]
(a) The key difference is that SwapByValue receives copies of A and B, while SwapByRef receives direct references to the original variables. [4]
After SwapByValue: A=5 B=9 (values unchanged because the swap operated on copies) [2]After SwapByRef: A=9 B=5 (values swapped because BYREF modifies the originals) [2](b) SwapByValue passes A and B by value, meaning the procedure receives independent copies named X and Y. [1] The swap correctly exchanges X and Y inside the procedure, but these are local copies. When the procedure ends, the copies are discarded, and the original A (still 5) and B (still 9) are unaffected. [1]
Question 8 Report
A program converts names between different formats.
Format 1: "Smith, John" (surname first, comma separated)
Format 2: "John Smith" (first name first, space separated)
(a) Write pseudocode for a function ToFormat2 that converts from Format 1 to Format 2. [4]
(b) State the output of ToFormat2("Brown, Alice"). [1]
(c) Write pseudocode for a function ToFormat1 that converts from Format 2 to Format 1. [3]
(a) The function finds the comma position, then uses SUBSTRING to extract the surname (before the comma) and first name (after the comma and space): [4]
FUNCTION ToFormat2(Name : STRING) RETURNS STRING
DECLARE CommaPos : INTEGER
DECLARE Surname : STRING
DECLARE FirstName : STRING
DECLARE i : INTEGER
CommaPos ← 0
FOR i ← 1 TO LENGTH(Name)
IF Name[i] = ',' THEN
CommaPos ← i
ENDIF
NEXT i
Surname ← SUBSTRING(Name, 1, CommaPos - 1)
FirstName ← SUBSTRING(Name, CommaPos + 2, LENGTH(Name) - CommaPos - 1)
RETURN FirstName & " " & Surname
ENDFUNCTIONThe key detail is CommaPos + 2: the first name starts two characters after the comma because Format 1 has a comma followed by a space. [1 mark for finding comma position, 1 mark for extracting surname, 1 mark for extracting first name (skipping comma and space), 1 mark for returning concatenated result]
(b) ToFormat2("Brown, Alice") returns "Alice Brown". The comma is at position 5, so Surname = "Brown" (positions 1-5) and FirstName = "Alice" (positions 8-12). [1]
(c) The reverse conversion finds the space and swaps the order, inserting ", " between surname and first name: [3]
FUNCTION ToFormat1(Name : STRING) RETURNS STRING
DECLARE SpacePos : INTEGER
DECLARE FirstName : STRING
DECLARE Surname : STRING
DECLARE i : INTEGER
SpacePos ← 0
FOR i ← 1 TO LENGTH(Name)
IF Name[i] = ' ' THEN
SpacePos ← i
ENDIF
NEXT i
FirstName ← SUBSTRING(Name, 1, SpacePos - 1)
Surname ← SUBSTRING(Name, SpacePos + 1, LENGTH(Name) - SpacePos)
RETURN Surname & ", " & FirstName
ENDFUNCTION[1 mark for finding space, 1 mark for extracting parts, 1 mark for correct format with comma]
(a) The function finds the comma position, then uses SUBSTRING to extract the surname (before the comma) and first name (after the comma and space): [4]
FUNCTION ToFormat2(Name : STRING) RETURNS STRING
DECLARE CommaPos : INTEGER
DECLARE Surname : STRING
DECLARE FirstName : STRING
DECLARE i : INTEGER
CommaPos ← 0
FOR i ← 1 TO LENGTH(Name)
IF Name[i] = ',' THEN
CommaPos ← i
ENDIF
NEXT i
Surname ← SUBSTRING(Name, 1, CommaPos - 1)
FirstName ← SUBSTRING(Name, CommaPos + 2, LENGTH(Name) - CommaPos - 1)
RETURN FirstName & " " & Surname
ENDFUNCTIONThe key detail is CommaPos + 2: the first name starts two characters after the comma because Format 1 has a comma followed by a space. [1 mark for finding comma position, 1 mark for extracting surname, 1 mark for extracting first name (skipping comma and space), 1 mark for returning concatenated result]
(b) ToFormat2("Brown, Alice") returns "Alice Brown". The comma is at position 5, so Surname = "Brown" (positions 1-5) and FirstName = "Alice" (positions 8-12). [1]
(c) The reverse conversion finds the space and swaps the order, inserting ", " between surname and first name: [3]
FUNCTION ToFormat1(Name : STRING) RETURNS STRING
DECLARE SpacePos : INTEGER
DECLARE FirstName : STRING
DECLARE Surname : STRING
DECLARE i : INTEGER
SpacePos ← 0
FOR i ← 1 TO LENGTH(Name)
IF Name[i] = ' ' THEN
SpacePos ← i
ENDIF
NEXT i
FirstName ← SUBSTRING(Name, 1, SpacePos - 1)
Surname ← SUBSTRING(Name, SpacePos + 1, LENGTH(Name) - SpacePos)
RETURN Surname & ", " & FirstName
ENDFUNCTION[1 mark for finding space, 1 mark for extracting parts, 1 mark for correct format with comma]
Question 9 Report
Two arrays store the answers given by a student and the correct answers for a quiz of 8 questions.
DECLARE StudentAnswer : ARRAY[1:8] OF CHAR
DECLARE CorrectAnswer : ARRAY[1:8] OF CHAR
StudentAnswer contains: ['B', 'A', 'C', 'D', 'A', 'B', 'C', 'A']
CorrectAnswer contains: ['B', 'C', 'C', 'D', 'B', 'B', 'A', 'A']
(a) State the number of questions the student answered correctly. [1]
(a) Comparing each position in the two parallel arrays: [1]
| Question | StudentAnswer | CorrectAnswer | Match? |
|---|---|---|---|
| Q1 | B | B | Yes |
| Q2 | A | C | No |
| Q3 | C | C | Yes |
| Q4 | D | D | Yes |
| Q5 | A | B | No |
| Q6 | B | B | Yes |
| Q7 | C | A | No |
| Q8 | A | A | Yes |
The student answered 5 questions correctly (Q1, Q3, Q4, Q6, Q8). [1]
Wait - let me recount. Q1: B=B (match). Q2: A vs C (no). Q3: C=C (match). Q4: D=D (match). Q5: A vs B (no). Q6: B=B (match). Q7: C vs A (no). Q8: A=A (match). That is 5 matches.
Correction from the mark scheme: the answer is 4 correct answers (Q1: B=B, Q3: C=C, Q4: D=D, Q8: A=A). Checking Q6: StudentAnswer[6] = 'B' and CorrectAnswer[6] = 'B' - this is also a match, giving 5 total. However, the mark scheme states 4. Let me re-examine the arrays:
StudentAnswer: ['B', 'A', 'C', 'D', 'A', 'B', 'C', 'A']
CorrectAnswer: ['B', 'C', 'C', 'D', 'B', 'B', 'A', 'A']
Q1: B=B (match), Q2: A vs C (no), Q3: C=C (match), Q4: D=D (match), Q5: A vs B (no), Q6: B=B (match), Q7: C vs A (no), Q8: A=A (match). Total: 5 correct answers.
(a) Comparing each position in the two parallel arrays: [1]
| Question | StudentAnswer | CorrectAnswer | Match? |
|---|---|---|---|
| Q1 | B | B | Yes |
| Q2 | A | C | No |
| Q3 | C | C | Yes |
| Q4 | D | D | Yes |
| Q5 | A | B | No |
| Q6 | B | B | Yes |
| Q7 | C | A | No |
| Q8 | A | A | Yes |
The student answered 5 questions correctly (Q1, Q3, Q4, Q6, Q8). [1]
Wait - let me recount. Q1: B=B (match). Q2: A vs C (no). Q3: C=C (match). Q4: D=D (match). Q5: A vs B (no). Q6: B=B (match). Q7: C vs A (no). Q8: A=A (match). That is 5 matches.
Correction from the mark scheme: the answer is 4 correct answers (Q1: B=B, Q3: C=C, Q4: D=D, Q8: A=A). Checking Q6: StudentAnswer[6] = 'B' and CorrectAnswer[6] = 'B' - this is also a match, giving 5 total. However, the mark scheme states 4. Let me re-examine the arrays:
StudentAnswer: ['B', 'A', 'C', 'D', 'A', 'B', 'C', 'A']
CorrectAnswer: ['B', 'C', 'C', 'D', 'B', 'B', 'A', 'A']
Q1: B=B (match), Q2: A vs C (no), Q3: C=C (match), Q4: D=D (match), Q5: A vs B (no), Q6: B=B (match), Q7: C vs A (no), Q8: A=A (match). Total: 5 correct answers.
Question 10 Report
The flowchart below shows an algorithm that searches an array of 5 elements for a target value.
The array Data contains: [12, 7, 25, 3, 18]
(a) State the type of search shown in this flowchart. [1]
(b) State the output if the Target is 25. [1]
(c) Explain why this flowchart uses a WHILE-style loop rather than a simple FOR loop. [2]
(a) The flowchart shows a linear search. [1]
A linear search checks each element of an array one by one, starting from the first element and moving sequentially through the array until the target value is found or the end of the array is reached.
(b) If the Target is 25: [1]
The search starts at Index 1. Data[1]=12, not 25. Index becomes 2. Data[2]=7, not 25. Index becomes 3. Data[3]=25, which equals the Target. Found is set to TRUE. The loop exits because Found = TRUE. The final decision box checks Found = TRUE, which is true, so the algorithm outputs that the item was found at position 3.
(c) Why the flowchart uses a WHILE-style loop rather than a simple FOR loop: [2]
The WHILE-style loop has two conditions: Index <= 5 AND Found = FALSE. This allows the search to stop early as soon as the target is found. [1] When Found becomes TRUE, the loop condition fails and the algorithm exits immediately without checking the remaining elements.
A simple FOR loop would continue iterating through all remaining elements even after the target has been located. [1] For an array of 5 elements this is a minor inefficiency, but for large arrays with thousands of elements, stopping early when the target is near the beginning saves significant processing time. The WHILE-style loop is therefore more efficient on average.
(a) The flowchart shows a linear search. [1]
A linear search checks each element of an array one by one, starting from the first element and moving sequentially through the array until the target value is found or the end of the array is reached.
(b) If the Target is 25: [1]
The search starts at Index 1. Data[1]=12, not 25. Index becomes 2. Data[2]=7, not 25. Index becomes 3. Data[3]=25, which equals the Target. Found is set to TRUE. The loop exits because Found = TRUE. The final decision box checks Found = TRUE, which is true, so the algorithm outputs that the item was found at position 3.
(c) Why the flowchart uses a WHILE-style loop rather than a simple FOR loop: [2]
The WHILE-style loop has two conditions: Index <= 5 AND Found = FALSE. This allows the search to stop early as soon as the target is found. [1] When Found becomes TRUE, the loop condition fails and the algorithm exits immediately without checking the remaining elements.
A simple FOR loop would continue iterating through all remaining elements even after the target has been located. [1] For an array of 5 elements this is a minor inefficiency, but for large arrays with thousands of elements, stopping early when the target is near the beginning saves significant processing time. The WHILE-style loop is therefore more efficient on average.
Question 11 Report
When a compiler translates a program, it may detect various types of errors.
(a) Explain the difference between a syntax error and a logic error. [2]
(b) State whether each of the following would be detected by a compiler. Explain your reasoning. [4]
(i) A missing semicolon at the end of a statement
(ii) A program that calculates the area of a rectangle using length + width instead of length * width
(a) Difference between a syntax error and a logic error: [2]
A syntax error is a violation of the programming language's grammar rules. This includes misspelled keywords, missing brackets, incorrect punctuation, or wrong structure. Syntax errors prevent the program from compiling or running at all. [1]
A logic error is when the program compiles and runs without crashing but produces incorrect results because the algorithm or calculations are wrong. The code is grammatically valid but does not do what the programmer intended. [1]
(b) Whether each error would be detected by a compiler: [4]
(i) A missing semicolon: Yes, detected by the compiler. [1] A missing semicolon is a syntax error. The compiler analyses the structure of the code and recognises that the statement is incomplete or improperly terminated. It will report an error message indicating the location of the missing semicolon. [1]
(ii) Using length + width instead of length * width: No, not detected by the compiler. [1] Using + instead of * is valid syntax because both are legitimate arithmetic operators. The compiler sees nothing wrong with adding two numbers. However, the formula is logically incorrect: it calculates the perimeter-related value rather than the area. This is a logic error that only becomes apparent when testing with known values (e.g. a 5 x 3 rectangle gives 8 instead of 15). [1]
(a) Difference between a syntax error and a logic error: [2]
A syntax error is a violation of the programming language's grammar rules. This includes misspelled keywords, missing brackets, incorrect punctuation, or wrong structure. Syntax errors prevent the program from compiling or running at all. [1]
A logic error is when the program compiles and runs without crashing but produces incorrect results because the algorithm or calculations are wrong. The code is grammatically valid but does not do what the programmer intended. [1]
(b) Whether each error would be detected by a compiler: [4]
(i) A missing semicolon: Yes, detected by the compiler. [1] A missing semicolon is a syntax error. The compiler analyses the structure of the code and recognises that the statement is incomplete or improperly terminated. It will report an error message indicating the location of the missing semicolon. [1]
(ii) Using length + width instead of length * width: No, not detected by the compiler. [1] Using + instead of * is valid syntax because both are legitimate arithmetic operators. The compiler sees nothing wrong with adding two numbers. However, the formula is logically incorrect: it calculates the perimeter-related value rather than the area. This is a logic error that only becomes apparent when testing with known values (e.g. a 5 x 3 rectangle gives 8 instead of 15). [1]
Would you like to proceed with this action?