Loading....
|
Press & Hold to Drag Around |
|||
|
Click Here to Close |
|||
Question 1 Report
A system transmits ASCII characters using 7 data bits plus 1 even parity bit (8 bits total). The parity bit is the most significant (leftmost) bit.
(a) The ASCII codes for the characters A, B, C are 1000001, 1000010, 1000011. Add the even parity bit to each and show the complete 8-bit code. [3]
| Character | ASCII (7 bits) | Number of 1s | Parity bit | Complete byte |
|---|---|---|---|---|
| A | 1000001 | |||
| B | 1000010 | |||
| C | 1000011 |
(a) Adding even parity bits to ASCII codes (parity bit is the leftmost bit): [3]
| Character | ASCII (7 bits) | Number of 1s | Parity bit | Complete byte |
|---|---|---|---|---|
| A | 1000001 | 2 (even) | 0 | 01000001 |
| B | 1000010 | 2 (even) | 0 | 01000010 |
| C | 1000011 | 3 (odd) | 1 | 11000011 |
[1] for A (parity 0, byte 01000001), [1] for B (parity 0, byte 01000010), [1] for C (parity 1, byte 11000011).
For even parity, the total number of 1s in the complete 8-bit byte (including the parity bit) must be even. Characters A and B each have two 1s in their ASCII codes (already even), so the parity bit is 0. Character C has three 1s (odd), so the parity bit must be 1 to bring the total to four (even).
(a) Adding even parity bits to ASCII codes (parity bit is the leftmost bit): [3]
| Character | ASCII (7 bits) | Number of 1s | Parity bit | Complete byte |
|---|---|---|---|---|
| A | 1000001 | 2 (even) | 0 | 01000001 |
| B | 1000010 | 2 (even) | 0 | 01000010 |
| C | 1000011 | 3 (odd) | 1 | 11000011 |
[1] for A (parity 0, byte 01000001), [1] for B (parity 0, byte 01000010), [1] for C (parity 1, byte 11000011).
For even parity, the total number of 1s in the complete 8-bit byte (including the parity bit) must be even. Characters A and B each have two 1s in their ASCII codes (already even), so the parity bit is 0. Character C has three 1s (odd), so the parity bit must be 1 to bring the total to four (even).
Question 2 Report
A system requires users to create a password that meets the following rules:
(a) Write pseudocode for a function called CheckPassword that takes a string parameter and returns TRUE if the password meets all three rules, or FALSE otherwise. [5]
(a) The function checks three password rules: length between 8 and 20, at least one uppercase letter, and at least one digit. It loops through each character, setting flags when an uppercase letter or digit is found:
FUNCTION CheckPassword(Password : STRING) RETURNS BOOLEAN
DECLARE Length : INTEGER
DECLARE HasUpper : BOOLEAN
DECLARE HasDigit : BOOLEAN
DECLARE i : INTEGER
DECLARE Ch : CHAR
Length <- LENGTH(Password)
IF Length < 8 OR Length > 20 THEN
RETURN FALSE
ENDIF
HasUpper <- FALSE
HasDigit <- FALSE
FOR i <- 1 TO Length
Ch <- Password[i]
IF Ch >= 'A' AND Ch <= 'Z' THEN
HasUpper <- TRUE
ENDIF
IF Ch >= '0' AND Ch <= '9' THEN
HasDigit <- TRUE
ENDIF
NEXT i
IF HasUpper = TRUE AND HasDigit = TRUE THEN
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNCTIONThe length check provides an early exit for passwords that are too short or too long. The loop sets Boolean flags for each required character type, and the final check ensures both flags are TRUE. [5]
(a) The function checks three password rules: length between 8 and 20, at least one uppercase letter, and at least one digit. It loops through each character, setting flags when an uppercase letter or digit is found:
FUNCTION CheckPassword(Password : STRING) RETURNS BOOLEAN
DECLARE Length : INTEGER
DECLARE HasUpper : BOOLEAN
DECLARE HasDigit : BOOLEAN
DECLARE i : INTEGER
DECLARE Ch : CHAR
Length <- LENGTH(Password)
IF Length < 8 OR Length > 20 THEN
RETURN FALSE
ENDIF
HasUpper <- FALSE
HasDigit <- FALSE
FOR i <- 1 TO Length
Ch <- Password[i]
IF Ch >= 'A' AND Ch <= 'Z' THEN
HasUpper <- TRUE
ENDIF
IF Ch >= '0' AND Ch <= '9' THEN
HasDigit <- TRUE
ENDIF
NEXT i
IF HasUpper = TRUE AND HasDigit = TRUE THEN
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNCTIONThe length check provides an early exit for passwords that are too short or too long. The loop sets Boolean flags for each required character type, and the final check ensures both flags are TRUE. [5]
Question 3 Report
A car's warning light system uses the following logic:
Let F = fuel low, T = engine temperature high, D = door open, M = car moving, and W = warning light.
(a) Write the Boolean expression for W. [3]
(b) Complete the truth table for the following selected input combinations. [3]
| F | T | D | M | F OR T | D AND M | W |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | |||
| 1 | 0 | 0 | 0 | |||
| 0 | 0 | 1 | 1 | |||
| 0 | 1 | 1 | 0 | |||
| 1 | 1 | 1 | 1 |
(c) State the value of W when the fuel is not low, the temperature is normal, the door is open, but the car is stationary. [2]
(d) State how many logic gates would be needed to build this circuit. Name each gate type. [2]
(e) Write the Boolean expression for the output of the circuit shown above. [2]
(f) Complete the truth table for a logic circuit with three inputs A, B and C that outputs 1 only when at least two inputs are 1. [3]
(a) Boolean expression for the warning light W: [3]
W = (F OR T) OR (D AND M)
[1] for F OR T (fuel low or temperature high), [1] for D AND M (door open and car moving), [1] for combining both with OR.
The warning light activates if either condition is met: a fuel/temperature problem, or a door-while-moving situation. The OR at the top level means satisfying either sub-condition is enough.
(b) Completed truth table: [3]
| F | T | D | M | F OR T | D AND M | W |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 | 1 | 0 | 1 |
| 0 | 0 | 1 | 1 | 0 | 1 | 1 |
| 0 | 1 | 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 | 1 | 1 |
[1] for F OR T column correct, [1] for D AND M column correct, [1] for W column correct.
Row 1: no problems, W=0. Row 2: fuel low, W=1. Row 3: door open while moving, W=1. Row 4: engine hot (temperature), W=1. Row 5: all problems present, W=1.
(c) When fuel is not low (F=0), temperature is normal (T=0), door is open (D=1), car is stationary (M=0): [2]
W = (0 OR 0) OR (1 AND 0) = 0 OR 0 = 0
The warning light is OFF. [1] Neither condition is triggered: fuel and temperature are fine, and although the door is open, the car is not moving so D AND M = 0. [1]
(d) Number of logic gates needed: 3 gates [1]
(e) The output expression for the described circuit is: Z = (A AND B) OR (NOT C) [1 for correct operators, 1 for correct structure].
(f) Truth table where the output is 1 when at least two inputs are 1: [3]
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
[1] for rows where output is 0 (fewer than two 1s), [1] for rows with exactly two 1s giving output 1, [1] for the row with all three 1s also giving output 1. This is known as a majority function.
(a) Boolean expression for the warning light W: [3]
W = (F OR T) OR (D AND M)
[1] for F OR T (fuel low or temperature high), [1] for D AND M (door open and car moving), [1] for combining both with OR.
The warning light activates if either condition is met: a fuel/temperature problem, or a door-while-moving situation. The OR at the top level means satisfying either sub-condition is enough.
(b) Completed truth table: [3]
| F | T | D | M | F OR T | D AND M | W |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 | 1 | 0 | 1 |
| 0 | 0 | 1 | 1 | 0 | 1 | 1 |
| 0 | 1 | 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 | 1 | 1 |
[1] for F OR T column correct, [1] for D AND M column correct, [1] for W column correct.
Row 1: no problems, W=0. Row 2: fuel low, W=1. Row 3: door open while moving, W=1. Row 4: engine hot (temperature), W=1. Row 5: all problems present, W=1.
(c) When fuel is not low (F=0), temperature is normal (T=0), door is open (D=1), car is stationary (M=0): [2]
W = (0 OR 0) OR (1 AND 0) = 0 OR 0 = 0
The warning light is OFF. [1] Neither condition is triggered: fuel and temperature are fine, and although the door is open, the car is not moving so D AND M = 0. [1]
(d) Number of logic gates needed: 3 gates [1]
(e) The output expression for the described circuit is: Z = (A AND B) OR (NOT C) [1 for correct operators, 1 for correct structure].
(f) Truth table where the output is 1 when at least two inputs are 1: [3]
| A | B | C | Output |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 |
[1] for rows where output is 0 (fewer than two 1s), [1] for rows with exactly two 1s giving output 1, [1] for the row with all three 1s also giving output 1. This is known as a majority function.
Question 4 Report
Study the following pseudocode that converts a number of seconds into hours, minutes and seconds.
DECLARE TotalSeconds : INTEGER
DECLARE Hours : INTEGER
DECLARE Minutes : INTEGER
DECLARE Seconds : INTEGER
INPUT TotalSeconds
Hours ← TotalSeconds DIV 3600
TotalSeconds ← TotalSeconds MOD 3600
Minutes ← TotalSeconds DIV 60
Seconds ← TotalSeconds MOD 60
OUTPUT Hours, ":", Minutes, ":", Seconds(a) Complete the trace table for the input TotalSeconds = 7384. [4]
| Step | TotalSeconds | Hours | Minutes | Seconds |
|---|---|---|---|---|
| Input | ||||
| Hours calc | ||||
| Remaining secs | ||||
| Minutes calc | ||||
| Seconds calc |
(b) State the output. [1]
(c) Explain the difference between the DIV and MOD operators. [1]
(a) The algorithm converts a total number of seconds into hours, minutes, and remaining seconds using DIV (integer division) and MOD (remainder):
| Step | TotalSeconds | Hours | Minutes | Seconds |
|---|---|---|---|---|
| Input | 7384 | - | - | - |
| Hours calc | 7384 | 7384 DIV 3600 = 2 | - | - |
| Remaining secs | 7384 MOD 3600 = 184 | 2 | - | - |
| Minutes calc | 184 | 2 | 184 DIV 60 = 3 | - |
| Seconds calc | 184 | 2 | 3 | 184 MOD 60 = 4 |
The key insight is that DIV extracts the whole units (hours or minutes) and MOD gives the remainder that still needs to be broken down further. [4]
(b) The output is: 2:3:4 (2 hours, 3 minutes, 4 seconds). [1]
(c) DIV performs integer division, returning only the whole number part and discarding the remainder. For example, 7384 DIV 3600 = 2 (not 2.051...). MOD returns only the remainder after integer division. For example, 7384 MOD 3600 = 184. Together, they allow decomposition of a large value into its component parts. [1]
(a) The algorithm converts a total number of seconds into hours, minutes, and remaining seconds using DIV (integer division) and MOD (remainder):
| Step | TotalSeconds | Hours | Minutes | Seconds |
|---|---|---|---|---|
| Input | 7384 | - | - | - |
| Hours calc | 7384 | 7384 DIV 3600 = 2 | - | - |
| Remaining secs | 7384 MOD 3600 = 184 | 2 | - | - |
| Minutes calc | 184 | 2 | 184 DIV 60 = 3 | - |
| Seconds calc | 184 | 2 | 3 | 184 MOD 60 = 4 |
The key insight is that DIV extracts the whole units (hours or minutes) and MOD gives the remainder that still needs to be broken down further. [4]
(b) The output is: 2:3:4 (2 hours, 3 minutes, 4 seconds). [1]
(c) DIV performs integer division, returning only the whole number part and discarding the remainder. For example, 7384 DIV 3600 = 2 (not 2.051...). MOD returns only the remainder after integer division. For example, 7384 MOD 3600 = 184. Together, they allow decomposition of a large value into its component parts. [1]
Question 5 Report
Study the following pseudocode that processes an array of integers.
DECLARE Nums : ARRAY[1:6] OF INTEGER
DECLARE Temp : INTEGER
DECLARE i : INTEGER
DECLARE Swapped : BOOLEAN
Nums[1] ← 8
Nums[2] ← 3
Nums[3] ← 5
Nums[4] ← 1
Nums[5] ← 9
Nums[6] ← 2
REPEAT
Swapped ← FALSE
FOR i ← 1 TO 5
IF Nums[i] > Nums[i + 1] THEN
Temp ← Nums[i]
Nums[i] ← Nums[i + 1]
Nums[i + 1] ← Temp
Swapped ← TRUE
ENDIF
NEXT i
UNTIL Swapped = FALSE(a) Complete the table to show the contents of the array after the first complete pass of the outer loop. [4]
| Nums[1] | Nums[2] | Nums[3] | Nums[4] | Nums[5] | Nums[6] |
|---|---|---|---|---|---|
(b) Name the sorting algorithm being used. [1]
(c) State the purpose of the variable Temp. [1]
(d) Explain why the variable Swapped is used. [2]
(e) State the minimum and maximum number of complete passes needed to sort an array of 6 elements using this algorithm. [2]
(a) The algorithm is a bubble sort. Starting with [8, 3, 5, 1, 9, 2], the inner FOR loop compares each adjacent pair from position 1 to 5:
| Comparison | Elements | Swap? | Array after |
|---|---|---|---|
| i=1: Nums[1] vs Nums[2] | 8 vs 3 | Yes | [3, 8, 5, 1, 9, 2] |
| i=2: Nums[2] vs Nums[3] | 8 vs 5 | Yes | [3, 5, 8, 1, 9, 2] |
| i=3: Nums[3] vs Nums[4] | 8 vs 1 | Yes | [3, 5, 1, 8, 9, 2] |
| i=4: Nums[4] vs Nums[5] | 8 vs 9 | No | [3, 5, 1, 8, 9, 2] |
| i=5: Nums[5] vs Nums[6] | 9 vs 2 | Yes | [3, 5, 1, 8, 2, 9] |
After the first complete pass, the array is: [3, 5, 1, 8, 2, 9]. The largest value (9) has "bubbled" to its correct final position. [4]
(b) The sorting algorithm is a bubble sort. It works by repeatedly comparing adjacent elements and swapping them if they are in the wrong order. [1]
(c) Temp is a temporary variable used to hold one value during the swap of two adjacent elements. Without it, one value would be overwritten and lost when the other is copied into its place. The three-step swap pattern (Temp <- A, A <- B, B <- Temp) preserves both values. [1]
(d) Swapped is a Boolean flag that tracks whether any swaps occurred during a complete pass through the array. [1] If no swaps were made during an entire pass (Swapped remains FALSE), the array is already sorted and the REPEAT loop terminates early. Without this flag, the algorithm would continue making unnecessary passes even after the array is fully sorted. [1] [2]
(e) Minimum: 1 pass. If the array is already sorted, one pass through the inner loop produces no swaps, so Swapped stays FALSE and the algorithm terminates after just that single pass. [1]
Maximum: 5 passes (n - 1 = 6 - 1 = 5). In the worst case (reverse-sorted array), each pass moves only one element to its correct position, requiring 5 passes to sort all 6 elements. [1] [2]
(a) The algorithm is a bubble sort. Starting with [8, 3, 5, 1, 9, 2], the inner FOR loop compares each adjacent pair from position 1 to 5:
| Comparison | Elements | Swap? | Array after |
|---|---|---|---|
| i=1: Nums[1] vs Nums[2] | 8 vs 3 | Yes | [3, 8, 5, 1, 9, 2] |
| i=2: Nums[2] vs Nums[3] | 8 vs 5 | Yes | [3, 5, 8, 1, 9, 2] |
| i=3: Nums[3] vs Nums[4] | 8 vs 1 | Yes | [3, 5, 1, 8, 9, 2] |
| i=4: Nums[4] vs Nums[5] | 8 vs 9 | No | [3, 5, 1, 8, 9, 2] |
| i=5: Nums[5] vs Nums[6] | 9 vs 2 | Yes | [3, 5, 1, 8, 2, 9] |
After the first complete pass, the array is: [3, 5, 1, 8, 2, 9]. The largest value (9) has "bubbled" to its correct final position. [4]
(b) The sorting algorithm is a bubble sort. It works by repeatedly comparing adjacent elements and swapping them if they are in the wrong order. [1]
(c) Temp is a temporary variable used to hold one value during the swap of two adjacent elements. Without it, one value would be overwritten and lost when the other is copied into its place. The three-step swap pattern (Temp <- A, A <- B, B <- Temp) preserves both values. [1]
(d) Swapped is a Boolean flag that tracks whether any swaps occurred during a complete pass through the array. [1] If no swaps were made during an entire pass (Swapped remains FALSE), the array is already sorted and the REPEAT loop terminates early. Without this flag, the algorithm would continue making unnecessary passes even after the array is fully sorted. [1] [2]
(e) Minimum: 1 pass. If the array is already sorted, one pass through the inner loop produces no swaps, so Swapped stays FALSE and the algorithm terminates after just that single pass. [1]
Maximum: 5 passes (n - 1 = 6 - 1 = 5). In the worst case (reverse-sorted array), each pass moves only one element to its correct position, requiring 5 passes to sort all 6 elements. [1] [2]
Question 6 Report
A program uses a sentinel value to control input into an array.
DECLARE Numbers : ARRAY[1:20] OF INTEGER
DECLARE Count : INTEGER
DECLARE Value : INTEGER
Count <- 0
OUTPUT "Enter numbers (-1 to stop):"
INPUT Value
WHILE Value <> -1 AND Count < 20
Count <- Count + 1
Numbers[Count] <- Value
INPUT Value
ENDWHILE
OUTPUT Count, " numbers entered"
(a) State what a sentinel value is, using this example. [2]
(b) If the user enters: 15, 8, 42, 3, -1, state the contents of the array and the value of Count. [2]
(c) Explain the purpose of the condition Count < 20 in the WHILE loop. [2]
(d) Write pseudocode to extend the program so it also calculates and outputs the average of the numbers entered (after the loop). [2]
(e) State one advantage of using a sentinel value compared to asking the user in advance how many numbers they want to enter. [1]
(a) A sentinel value is a special value that signals the end of data input, rather than being part of the actual data. [1] In this example, -1 is the sentinel. When the user enters -1, the WHILE loop condition Value <> -1 becomes false, causing the loop to exit. The value -1 itself is never stored in the array because the check happens before the assignment. [1]
(b) If the user enters 15, 8, 42, 3, -1: [2]
Array contents: Numbers[1]=15, Numbers[2]=8, Numbers[3]=42, Numbers[4]=3 [1]
Count = 4 [1]
The sentinel value -1 terminates the loop and is not stored. Positions 5-20 remain unchanged (uninitialised).
(c) Purpose of Count < 20 in the WHILE loop: [2]
It prevents the array from overflowing by ensuring no more than 20 values can be stored. [1] Without this guard, if the user enters more than 20 values without typing -1, the program would attempt to write to Numbers[21], which is beyond the array bounds and would cause a runtime error (array index out of bounds). [1]
(d) Pseudocode to calculate and output the average after the loop: [2]
IF Count > 0
THEN
DECLARE Total : INTEGER
Total <- 0
FOR Index <- 1 TO Count
Total <- Total + Numbers[Index]
NEXT Index
OUTPUT "Average: ", Total / Count
ENDIF[1] for calculating the total using a loop that runs to Count (not to 20, which would include uninitialised values), [1] for dividing by Count and handling the edge case where Count = 0 (division by zero).
(e) Advantage of a sentinel value over pre-specifying the count: [1]
The user does not need to know in advance how many numbers they will enter. [1] They can enter as many or as few values as needed and simply type the sentinel value when finished. This is more flexible and user-friendly, especially when the number of items is not known beforehand.
(a) A sentinel value is a special value that signals the end of data input, rather than being part of the actual data. [1] In this example, -1 is the sentinel. When the user enters -1, the WHILE loop condition Value <> -1 becomes false, causing the loop to exit. The value -1 itself is never stored in the array because the check happens before the assignment. [1]
(b) If the user enters 15, 8, 42, 3, -1: [2]
Array contents: Numbers[1]=15, Numbers[2]=8, Numbers[3]=42, Numbers[4]=3 [1]
Count = 4 [1]
The sentinel value -1 terminates the loop and is not stored. Positions 5-20 remain unchanged (uninitialised).
(c) Purpose of Count < 20 in the WHILE loop: [2]
It prevents the array from overflowing by ensuring no more than 20 values can be stored. [1] Without this guard, if the user enters more than 20 values without typing -1, the program would attempt to write to Numbers[21], which is beyond the array bounds and would cause a runtime error (array index out of bounds). [1]
(d) Pseudocode to calculate and output the average after the loop: [2]
IF Count > 0
THEN
DECLARE Total : INTEGER
Total <- 0
FOR Index <- 1 TO Count
Total <- Total + Numbers[Index]
NEXT Index
OUTPUT "Average: ", Total / Count
ENDIF[1] for calculating the total using a loop that runs to Count (not to 20, which would include uninitialised values), [1] for dividing by Count and handling the edge case where Count = 0 (division by zero).
(e) Advantage of a sentinel value over pre-specifying the count: [1]
The user does not need to know in advance how many numbers they will enter. [1] They can enter as many or as few values as needed and simply type the sentinel value when finished. This is more flexible and user-friendly, especially when the number of items is not known beforehand.
Question 7 Report
An array Names[1:20] stores the names of 20 students in a class. Some names may appear more than once if students share the same name.
(a) Write pseudocode for a function CountOccurrences that takes a name as a parameter and returns how many times it appears in the array. [3]
(b) Write pseudocode that uses CountOccurrences to find and output all names that appear more than once. Your solution should not output the same name twice. [4]
(c) State the output of CountOccurrences("Aisha") if "Aisha" appears at positions 3, 8, and 15. [1]
(a) The CountOccurrences function iterates through the entire array, comparing each element to the target name and incrementing a counter for each match: [3]
FUNCTION CountOccurrences(Target : STRING) RETURNS INTEGER
DECLARE Count : INTEGER
DECLARE i : INTEGER
Count ← 0
FOR i ← 1 TO 20
IF Names[i] = Target THEN
Count ← Count + 1
ENDIF
NEXT i
RETURN Count
ENDFUNCTION[1 mark for loop, 1 mark for comparison and counting, 1 mark for return]
(b) To find duplicates without reporting the same name twice, the algorithm checks earlier positions in the array. If the same name appears at a lower index, it has already been reported: [4]
DECLARE i : INTEGER
DECLARE j : INTEGER
DECLARE AlreadyReported : BOOLEAN
FOR i ← 1 TO 20
IF CountOccurrences(Names[i]) > 1 THEN
AlreadyReported ← FALSE
FOR j ← 1 TO i - 1
IF Names[j] = Names[i] THEN
AlreadyReported ← TRUE
ENDIF
NEXT j
IF AlreadyReported = FALSE THEN
OUTPUT Names[i], " appears ", CountOccurrences(Names[i]), " times"
ENDIF
ENDIF
NEXT iThe inner loop from 1 to i-1 checks whether Names[i] appeared earlier. If it did, this occurrence is a later duplicate and skipping it prevents the same name from being output more than once. [1 mark for checking count > 1, 1 mark for preventing duplicate output, 1 mark for checking earlier positions, 1 mark for correct output]
(c) CountOccurrences("Aisha") returns 3, because "Aisha" appears at positions 3, 8, and 15 in the array, giving a count of three matches. [1]
(a) The CountOccurrences function iterates through the entire array, comparing each element to the target name and incrementing a counter for each match: [3]
FUNCTION CountOccurrences(Target : STRING) RETURNS INTEGER
DECLARE Count : INTEGER
DECLARE i : INTEGER
Count ← 0
FOR i ← 1 TO 20
IF Names[i] = Target THEN
Count ← Count + 1
ENDIF
NEXT i
RETURN Count
ENDFUNCTION[1 mark for loop, 1 mark for comparison and counting, 1 mark for return]
(b) To find duplicates without reporting the same name twice, the algorithm checks earlier positions in the array. If the same name appears at a lower index, it has already been reported: [4]
DECLARE i : INTEGER
DECLARE j : INTEGER
DECLARE AlreadyReported : BOOLEAN
FOR i ← 1 TO 20
IF CountOccurrences(Names[i]) > 1 THEN
AlreadyReported ← FALSE
FOR j ← 1 TO i - 1
IF Names[j] = Names[i] THEN
AlreadyReported ← TRUE
ENDIF
NEXT j
IF AlreadyReported = FALSE THEN
OUTPUT Names[i], " appears ", CountOccurrences(Names[i]), " times"
ENDIF
ENDIF
NEXT iThe inner loop from 1 to i-1 checks whether Names[i] appeared earlier. If it did, this occurrence is a later duplicate and skipping it prevents the same name from being output more than once. [1 mark for checking count > 1, 1 mark for preventing duplicate output, 1 mark for checking earlier positions, 1 mark for correct output]
(c) CountOccurrences("Aisha") returns 3, because "Aisha" appears at positions 3, 8, and 15 in the array, giving a count of three matches. [1]
Question 8 Report
The flowchart below shows an algorithm that processes an array of 5 numbers.
The array Nums contains: [14, 8, 22, 3, 11]
(a) State what this algorithm does. [1]
(b) Trace through the algorithm and complete the table. [4]
| I | Nums[I] | Nums[I] < Min? | Min |
|---|---|---|---|
| Start | |||
| 2 | |||
| 3 | |||
| 4 | |||
| 5 |
(c) State the output of the algorithm. [1]
(d) If the algorithm needed to find the maximum instead, state one change to the flowchart. [2]
(e) State why the loop starts at I = 2 rather than I = 1. [2]
(a) The algorithm finds the minimum (smallest) value in the array. [1]
It initialises Min to the first element, then compares each subsequent element to Min, updating Min whenever a smaller value is found.
(b) Trace table for Nums = [14, 8, 22, 3, 11]: [4]
| I | Nums[I] | Nums[I] < Min? | Min |
|---|---|---|---|
| Start | - | - | 14 |
| 2 | 8 | Yes (8 < 14) | 8 |
| 3 | 22 | No (22 < 8 is false) | 8 |
| 4 | 3 | Yes (3 < 8) | 3 |
| 5 | 11 | No (11 < 3 is false) | 3 |
[1] for correct Nums values, [1] for correct Yes/No comparisons, [1] for Min changing to 8 at I=2, [1] for Min changing to 3 at I=4.
(c) The output is: 3 [1]
(d) To find the maximum instead: change the comparison from Nums[I] < Min to Nums[I] > Min. [1] You would also rename the variable Min to Max for clarity. [1] With this change, the algorithm would track the largest value seen so far and output 22.
(e) The loop starts at I = 2 because Min is already initialised to Nums[1]. [1] Comparing Nums[1] against itself at I = 1 would be redundant since the result is always false (a value is never less than itself). Starting at I = 2 avoids this unnecessary comparison while still being correct because the first element has already been accounted for in the initialisation step. [1]
(a) The algorithm finds the minimum (smallest) value in the array. [1]
It initialises Min to the first element, then compares each subsequent element to Min, updating Min whenever a smaller value is found.
(b) Trace table for Nums = [14, 8, 22, 3, 11]: [4]
| I | Nums[I] | Nums[I] < Min? | Min |
|---|---|---|---|
| Start | - | - | 14 |
| 2 | 8 | Yes (8 < 14) | 8 |
| 3 | 22 | No (22 < 8 is false) | 8 |
| 4 | 3 | Yes (3 < 8) | 3 |
| 5 | 11 | No (11 < 3 is false) | 3 |
[1] for correct Nums values, [1] for correct Yes/No comparisons, [1] for Min changing to 8 at I=2, [1] for Min changing to 3 at I=4.
(c) The output is: 3 [1]
(d) To find the maximum instead: change the comparison from Nums[I] < Min to Nums[I] > Min. [1] You would also rename the variable Min to Max for clarity. [1] With this change, the algorithm would track the largest value seen so far and output 22.
(e) The loop starts at I = 2 because Min is already initialised to Nums[1]. [1] Comparing Nums[1] against itself at I = 1 would be redundant since the result is always false (a value is never less than itself). Starting at I = 2 avoids this unnecessary comparison while still being correct because the first element has already been accounted for in the initialisation step. [1]
Question 9 Report
An art gallery wants to create a database to manage its collection and exhibitions.
The gallery needs to store:
(a) Design three tables: ARTWORK, EXHIBITION, and DISPLAY. For each table, list field names with data types and identify the primary key. [4]
(a) This question tests your ability to design a relational database with appropriate tables, data types, and keys for a many-to-many relationship. [4]
ARTWORK table:
| Field Name | Data Type | Key |
|---|---|---|
| ArtworkID | INTEGER | Primary Key |
| Title | VARCHAR | |
| Artist | VARCHAR | |
| Medium | VARCHAR | |
| YearCreated | INTEGER | |
| EstimatedValue | REAL / DECIMAL |
[1] for sensible fields with types, [1] for primary key. EstimatedValue uses REAL or DECIMAL because monetary values require decimal precision.
EXHIBITION table:
| Field Name | Data Type | Key |
|---|---|---|
| ExhibitionID | INTEGER | Primary Key |
| ExhibitionName | VARCHAR | |
| StartDate | DATE | |
| EndDate | DATE | |
| GalleryRoom | VARCHAR |
[1] for sensible fields with types, [1] for primary key.
DISPLAY table (junction table):
| Field Name | Data Type | Key |
|---|---|---|
| DisplayID | INTEGER | Primary Key |
| ArtworkID | INTEGER | Foreign Key |
| ExhibitionID | INTEGER | Foreign Key |
[1] for both FK fields present, [1] for primary key.
The DISPLAY table resolves the many-to-many relationship: one artwork can appear in multiple exhibitions, and one exhibition can display multiple artworks. Each record in DISPLAY represents one specific artwork being shown in one specific exhibition. The foreign keys link back to ARTWORK and EXHIBITION respectively.
(a) This question tests your ability to design a relational database with appropriate tables, data types, and keys for a many-to-many relationship. [4]
ARTWORK table:
| Field Name | Data Type | Key |
|---|---|---|
| ArtworkID | INTEGER | Primary Key |
| Title | VARCHAR | |
| Artist | VARCHAR | |
| Medium | VARCHAR | |
| YearCreated | INTEGER | |
| EstimatedValue | REAL / DECIMAL |
[1] for sensible fields with types, [1] for primary key. EstimatedValue uses REAL or DECIMAL because monetary values require decimal precision.
EXHIBITION table:
| Field Name | Data Type | Key |
|---|---|---|
| ExhibitionID | INTEGER | Primary Key |
| ExhibitionName | VARCHAR | |
| StartDate | DATE | |
| EndDate | DATE | |
| GalleryRoom | VARCHAR |
[1] for sensible fields with types, [1] for primary key.
DISPLAY table (junction table):
| Field Name | Data Type | Key |
|---|---|---|
| DisplayID | INTEGER | Primary Key |
| ArtworkID | INTEGER | Foreign Key |
| ExhibitionID | INTEGER | Foreign Key |
[1] for both FK fields present, [1] for primary key.
The DISPLAY table resolves the many-to-many relationship: one artwork can appear in multiple exhibitions, and one exhibition can display multiple artworks. Each record in DISPLAY represents one specific artwork being shown in one specific exhibition. The foreign keys link back to ARTWORK and EXHIBITION respectively.
Question 10 Report
Study the following pseudocode that finds how many unique (distinct) values are in an array.
DECLARE Data : ARRAY[1:8] OF INTEGER
Data contains: [4, 7, 2, 7, 4, 9, 2, 4]
DECLARE UniqueCount : INTEGER
DECLARE IsUnique : BOOLEAN
UniqueCount <- 0
FOR I <- 1 TO 8
IsUnique <- TRUE
FOR J <- 1 TO I - 1
IF Data[J] = Data[I]
THEN
IsUnique <- FALSE
ENDIF
NEXT J
IF IsUnique = TRUE
THEN
UniqueCount <- UniqueCount + 1
OUTPUT Data[I]
ENDIF
NEXT I
OUTPUT "Total unique values: ", UniqueCount
(a) State the output of this program. [3]
(b) Explain the purpose of the inner loop FOR J <- 1 TO I - 1. [2]
(a) Output of the unique-value-finding program with Data = [4, 7, 2, 7, 4, 9, 2, 4]: [3]
4
7
2
9
Total unique values: 4[1] for the correct unique values (4, 7, 2, 9), [1] for correct order (first occurrence of each), [1] for the total count of 4.
Walkthrough: I=1: inner loop J runs 1 to 0 (does not execute), IsUnique stays TRUE, output 4. I=2: J checks Data[1]=4, no match with 7, IsUnique stays TRUE, output 7. I=3: J checks Data[1]=4 and Data[2]=7, no match with 2, output 2. I=4: J checks 4, 7, 2 against 7: Data[2]=7 matches Data[4]=7, IsUnique becomes FALSE, skip. I=5: Data[1]=4 matches Data[5]=4, FALSE, skip. I=6: no match found for 9, output 9. I=7: Data[3]=2 matches Data[7]=2, skip. I=8: Data[1]=4 matches Data[8]=4, skip.
(b) Purpose of the inner loop FOR J <- 1 TO I - 1: [2]
The inner loop checks all elements that appear before the current element (at positions 1 through I-1) to determine whether the current value has already been seen. [1] If any earlier element matches the current value, IsUnique is set to FALSE, indicating this is a duplicate that should not be counted or output again. By only looking backward (not forward), the algorithm ensures that only the first occurrence of each value is counted as unique. [1]
(a) Output of the unique-value-finding program with Data = [4, 7, 2, 7, 4, 9, 2, 4]: [3]
4
7
2
9
Total unique values: 4[1] for the correct unique values (4, 7, 2, 9), [1] for correct order (first occurrence of each), [1] for the total count of 4.
Walkthrough: I=1: inner loop J runs 1 to 0 (does not execute), IsUnique stays TRUE, output 4. I=2: J checks Data[1]=4, no match with 7, IsUnique stays TRUE, output 7. I=3: J checks Data[1]=4 and Data[2]=7, no match with 2, output 2. I=4: J checks 4, 7, 2 against 7: Data[2]=7 matches Data[4]=7, IsUnique becomes FALSE, skip. I=5: Data[1]=4 matches Data[5]=4, FALSE, skip. I=6: no match found for 9, output 9. I=7: Data[3]=2 matches Data[7]=2, skip. I=8: Data[1]=4 matches Data[8]=4, skip.
(b) Purpose of the inner loop FOR J <- 1 TO I - 1: [2]
The inner loop checks all elements that appear before the current element (at positions 1 through I-1) to determine whether the current value has already been seen. [1] If any earlier element matches the current value, IsUnique is set to FALSE, indicating this is a duplicate that should not be counted or output again. By only looking backward (not forward), the algorithm ensures that only the first occurrence of each value is counted as unique. [1]
Question 11 Report
A program processes currency values and needs to display them in a standard format with exactly 2 decimal places.
(a) Write pseudocode for a function FormatMoney that takes a REAL amount and returns a string in the format "X.YY" (always showing 2 decimal places). For example, 5.0 should return "5.00" and 12.5 should return "12.50". [4]
(b) State the output for each input. [2]
| Input | Output |
|---|---|
| 7.0 | |
| 15.999 |
(c) Explain why displaying currency values with consistent formatting is important. [2]
(a) The FormatMoney function converts a REAL amount into a string with exactly two decimal places.
FUNCTION FormatMoney(Amount : REAL) RETURNS STRING
DECLARE Whole : INTEGER
DECLARE Frac : INTEGER
DECLARE Result : STRING
Whole ← INT(Amount)
Frac ← INT((Amount - Whole) * 100 + 0.5)
IF Frac >= 100 THEN
Whole ← Whole + 1
Frac ← Frac - 100
ENDIF
Result ← NUM_TO_STR(Whole) & "."
IF Frac < 10 THEN
Result ← Result & "0" & NUM_TO_STR(Frac)
ELSE
Result ← Result & NUM_TO_STR(Frac)
ENDIF
RETURN Result
ENDFUNCTIONINT(Amount) extracts the whole part. [1] The fractional part is multiplied by 100 and rounded (adding 0.5 before truncation). [1] If rounding pushes Frac to 100 (e.g., 15.999 rounds to 16.00), the overflow is carried into Whole. [1] A leading zero is prepended for single-digit pence values (e.g., Frac = 0 becomes "00"). [1]
(b)
| Input | Output |
|---|---|
| 7.0 | "7.00" |
| 15.999 | "16.00" |
For 7.0: Whole = 7, Frac = INT(0 * 100 + 0.5) = 0. Since 0 < 10, a leading zero is added: "7.00". [1]
For 15.999: Whole = 15, Frac = INT(0.999 * 100 + 0.5) = INT(100.4) = 100. Since Frac >= 100, Whole becomes 16 and Frac becomes 0: "16.00". [1]
(c) Consistent formatting prevents confusion about the value displayed. [1] Without fixed decimal places, "5" and "5.00" represent the same value but look different. A value like "5.1" could be misread as 51 pence rather than 5 pounds 10 pence if the context is ambiguous. Uniform formatting makes financial data clearer for users and reduces the chance of misinterpretation. [1]
(a) The FormatMoney function converts a REAL amount into a string with exactly two decimal places.
FUNCTION FormatMoney(Amount : REAL) RETURNS STRING
DECLARE Whole : INTEGER
DECLARE Frac : INTEGER
DECLARE Result : STRING
Whole ← INT(Amount)
Frac ← INT((Amount - Whole) * 100 + 0.5)
IF Frac >= 100 THEN
Whole ← Whole + 1
Frac ← Frac - 100
ENDIF
Result ← NUM_TO_STR(Whole) & "."
IF Frac < 10 THEN
Result ← Result & "0" & NUM_TO_STR(Frac)
ELSE
Result ← Result & NUM_TO_STR(Frac)
ENDIF
RETURN Result
ENDFUNCTIONINT(Amount) extracts the whole part. [1] The fractional part is multiplied by 100 and rounded (adding 0.5 before truncation). [1] If rounding pushes Frac to 100 (e.g., 15.999 rounds to 16.00), the overflow is carried into Whole. [1] A leading zero is prepended for single-digit pence values (e.g., Frac = 0 becomes "00"). [1]
(b)
| Input | Output |
|---|---|
| 7.0 | "7.00" |
| 15.999 | "16.00" |
For 7.0: Whole = 7, Frac = INT(0 * 100 + 0.5) = 0. Since 0 < 10, a leading zero is added: "7.00". [1]
For 15.999: Whole = 15, Frac = INT(0.999 * 100 + 0.5) = INT(100.4) = 100. Since Frac >= 100, Whole becomes 16 and Frac becomes 0: "16.00". [1]
(c) Consistent formatting prevents confusion about the value displayed. [1] Without fixed decimal places, "5" and "5.00" represent the same value but look different. A value like "5.1" could be misread as 51 pence rather than 5 pounds 10 pence if the context is ambiguous. Uniform formatting makes financial data clearer for users and reduces the chance of misinterpretation. [1]
Would you like to proceed with this action?