Cambridge IAL · Thinka-original Practice Paper

2025 Cambridge IAL Computer Science (9618) Practice Paper with Answers

Thinka Nov 2025 (V3) Cambridge International A Level-Style Mock — Computer Science (9618)

300 marks420 mins2025
An original Thinka practice paper modelled on the structure and difficulty of the Nov 2025 (V3) Cambridge International A Level Computer Science (9618) paper. Not affiliated with or reproduced from Cambridge.

Paper 1 Theory Fundamentals

Answer all questions. Calculators must not be used.
21 Question · 60.800000000000004 marks
Question 1 · Short Answer / Definition
2.5 marks
Explain the term *character set* and describe how a character is represented in a computer system using Unicode.
Show answer & marking scheme

Worked solution

A character set is a mapping of characters/symbols to a set of unique numeric codes (binary values) that the computer system can process. In Unicode, each character is assigned a unique code point. It supports variable-width encodings (such as UTF-8 or UTF-16) or fixed-width encodings, enabling the representation of over a million distinct characters. This allows it to support virtually all written languages and emojis, whereas older ASCII standards are restricted to 128 characters.

Marking scheme

1 mark: Definition of 'character set' as a complete defined list of characters/symbols along with their corresponding binary representations. 1 mark: Explaining that Unicode assigns a unique binary value (code point, e.g., 8/16/32-bit) to each character. 0.5 marks: Stating the benefit of Unicode over ASCII (e.g., handles thousands of international characters/symbols, whereas ASCII is limited to 128 or 256 characters).
Question 2 · Short Answer / Definition
2.5 marks
Explain the purpose of a *watchdog timer* in an embedded system.
Show answer & marking scheme

Worked solution

An embedded system often operates continuously without human intervention. A watchdog timer is an independent hardware timing device that helps the system recover from software hangs, crashes, or infinite loops. It initializes with a set countdown value. During normal execution, the software periodically resets this timer to prevent it from reaching zero. If a software fault occurs, the timer expires (reaches zero) and triggers a hardware reset signal to restart the system.

Marking scheme

1 mark: Purpose is to automatically recover/reset the system if a software crash, freeze, or infinite loop occurs without human intervention. 1 mark: It functions as a countdown timer which the running software must periodically reset (or 'kick') during normal execution. 0.5 marks: If the timer reaches zero / expires, a hardware reset is triggered to reboot the system.
Question 3 · Short Answer / Definition
2.5 marks
Describe the role of the *Current Instruction Register (CIR)* in the Fetch-Execute cycle.
Show answer & marking scheme

Worked solution

The Current Instruction Register (CIR) is a register in the Control Unit of the CPU. Its role is to temporarily store the instruction that is currently being decoded and executed. At the end of the Fetch stage, the instruction is loaded into the CIR from the Memory Data Register (MDR). Once in the CIR, the instruction is split into its constituent parts: the opcode (the instruction operation) and the operand (the address or the actual data). The control unit then decodes the opcode to coordinate the execution.

Marking scheme

1 mark: Temporarily holds the instruction currently being decoded and executed. 1 mark: Receives the instruction from the Memory Data Register (MDR) at the end of the Fetch phase. 0.5 marks: Splits the instruction into its opcode (operation code) and operand(s) for decoding by the control unit.
Question 4 · Short Answer / Definition
2.5 marks
Explain the difference between *lossy compression* and *lossless compression*, and state why lossless compression must be used for a program executable file.
Show answer & marking scheme

Worked solution

Lossy compression algorithms achieve smaller file sizes by permanently discarding redundant or less perceptible data (common in audio/image files). Lossless compression reduces file size by reorganizing or indexing data without discarding any information, allowing the original file to be reconstructed exactly. An executable file contains binary machine code instructions. If lossy compression were used, some bits would be lost, altering the instructions. Even a single changed bit can make the program corrupt, causing execution failure or critical runtime errors.

Marking scheme

1 mark: Lossy compression permanently discards data to reduce file size, whereas lossless compression retains all data and allows exact recreation. 1 mark: Executable files contain binary instructions/machine code that require 100% precision. 0.5 marks: Any loss of data (even a single bit) will corrupt the program code, making it unusable or causing crashes.
Question 5 · Short Answer / Definition
2.5 marks
Define the term *data validation* and explain how a *limit check* differs from a *range check*.
Show answer & marking scheme

Worked solution

Data validation is an automatic check carried out by a program on input data to ensure that it is sensible, complete, and reasonable before processing. A range check sets both an upper and a lower boundary for a data value (e.g., an exam mark must be between 0 and 100 inclusive). A limit check, however, only checks a single boundary—either a maximum allowed value or a minimum allowed value (e.g., checking only that age is greater than or equal to 18, with no upper bound, or checking only that a payment amount is less than a maximum limit).

Marking scheme

1 mark: Definition: An automatic program check to ensure input data is sensible, reasonable, complete, or conforms to specified rules (do not accept 'ensuring data is correct/accurate'). 1 mark: Range check verifies data lies between both a minimum and maximum boundary. 0.5 marks: Limit check only verifies a single boundary (either an upper limit or a lower limit, but not both).
Question 6 · Short Answer / Definition
2.5 marks
In the context of floating-point representations, define *normalization* and state two reasons why floating-point numbers are normalized.
Show answer & marking scheme

Worked solution

Normalization is the process of adjusting the mantissa and exponent of a floating-point number so that the mantissa starts with a standard bit pattern. In two's complement, a normalized positive number starts with '01' and a normalized negative number starts with '10'. Reasons for normalization: 1) Precision: It eliminates redundant leading zeros (or ones), ensuring the maximum number of significant bits are stored in the mantissa, reducing truncation/rounding errors. 2) Uniqueness: It ensures there is only one unique binary representation for each non-zero real number, making comparison operations simpler and faster.

Marking scheme

1 mark: Definition: Adjusting the mantissa and exponent so the mantissa begins with '01' (positive) or '10' (negative) in two's complement, eliminating redundant leading digits. 1 mark: Reason 1: Maximizes the precision/accuracy of the value by utilizing the full width of the mantissa. 0.5 marks: Reason 2: Ensures there is a unique, standardized representation for every real number (facilitating easier comparisons).
Question 7 · Short Answer / Definition
2.5 marks
State what is meant by a *virtual machine* and explain how a virtual machine can protect the host operating system from malware.
Show answer & marking scheme

Worked solution

A virtual machine (VM) is a software environment that emulates a complete, separate physical computer system, including its own operating system and virtual hardware resources. This virtualization is managed by software called a hypervisor. VMs protect host operating systems through isolation (sandboxing). The VM operates inside a strictly confined environment. If malware infects the VM, it remains isolated within that virtual environment. The malware cannot directly access the host system's file directories or physical memory spaces. If the VM is compromised, it can be deleted or reverted to a safe, clean snapshot without affecting the host operating system.

Marking scheme

1 mark: Definition: Software that emulates/creates a virtual representation of a physical computer running its own OS. 1 mark: Isolation: The VM is sandboxed / isolated from the host OS and other systems by a hypervisor. 0.5 marks: Security: Malware is restricted to the virtual disk and cannot write to or corrupt the host OS files or memory, allowing safe containment.
Question 8 · Short Answer / Definition
2.5 marks
Explain the role of the *syntax analyser* phase within a compiler.
Show answer & marking scheme

Worked solution

The syntax analyser is the second phase of a compiler. Its main role is to take the stream of tokens output by the lexical analyser and verify if they form grammatically correct statements according to the syntax rules of the source language. It builds an abstract syntax tree (or parse tree) to represent the hierarchical structure of the statements. If the code violates any syntax rules (such as missing brackets, incorrect keyword order), the syntax analyser generates syntax error reports and terminates compilation or continues checking for further errors.

Marking scheme

1 mark: Checks the tokens from the lexical analyser against the grammar/syntax rules of the programming language. 1 mark: Constructs a syntax tree (or parse tree) representing the hierarchical structure of the statements. 0.5 marks: Identifies and reports syntax errors (such as mismatched parentheses or incorrect statement structures).
Question 9 · Short Answer
2.5 marks
Explain the purpose of the intermediate code (bytecode) produced by some compilers and explain how a Virtual Machine (VM) utilizes this code.
Show answer & marking scheme

Worked solution

Bytecode serves as a middle layer between high-level source code and hardware-specific machine code. The VM executes this bytecode, acting as an abstraction layer over the host platform's physical CPU. Direct benefit is that developers write and compile code once, which can then be executed on multiple physical architectures without recompiling.

Marking scheme

1 mark: Identifying bytecode as intermediate/machine-independent code.
1 mark: Explaining that the VM interprets or compiles (JIT) this bytecode into the local processor's native machine instructions.
0.5 mark: Pointing out the resulting benefit of platform independence (portability).
Question 10 · Short Answer
2.5 marks
Describe Nyquist's sampling theorem and explain why adhering to this theorem is critical when digitizing analogue sound waves.
Show answer & marking scheme

Worked solution

By sampling at a rate higher than twice the maximum frequency (\(f_s \ge 2 \times f_{max}\)), the original analogue sound wave can be reconstructed with perfect fidelity. Since human hearing caps at approximately 20 kHz, audio digitizers typically use at least 40 kHz (or standard 44.1 kHz) to satisfy the Nyquist rate for human audio perception.

Marking scheme

1 mark: Correctly stating the Nyquist theorem (sampling frequency must be at least double the highest frequency of the analogue signal).
1 mark: Stating the purpose (prevents distortion / prevents aliasing / ensures accurate reconstruction of the original waveform).
0.5 mark: Providing a practical context (e.g., standard human audio frequency limit of 20 kHz requires at least 40 kHz sampling rate).
Question 11 · Short Answer
2.5 marks
Compare immediate addressing and direct addressing modes in assembly language instructions, outlining how the operand is accessed in each mode.
Show answer & marking scheme

Worked solution

Immediate addressing: e.g., LDD #45 (loads the constant value 45 directly into the accumulator). Direct addressing: e.g., LDD 45 (looks up address 45 in RAM and loads the value found there into the accumulator).

Marking scheme

1 mark: Clearly explaining immediate addressing (the data value is hardcoded directly inside the instruction).
1 mark: Clearly explaining direct addressing (the instruction holds the address of the data in memory).
0.5 mark: Comparing their execution/access characteristics (immediate requires zero memory read cycles for data retrieval, direct requires one memory access cycle).
Question 12 · Short Answer
2.5 marks
Explain how an operating system manages memory using the technique of paging, and state one disadvantage associated with this method.
Show answer & marking scheme

Worked solution

Under paging, the OS keeps track of mapped pages via page tables. When a process requests memory, physical frames do not need to be contiguous. Disadvantage: It can lead to internal fragmentation (on the very last page of a process) and can cause disk thrashing if virtual memory swapping becomes too frequent.

Marking scheme

1 mark: Explaining the division of memory into fixed-size pages (logical) and frames (physical).
1 mark: Explaining the role of the page table in mapping logical pages to non-contiguous physical memory locations.
0.5 mark: Identifying a valid disadvantage (e.g., overhead of managing page tables, risk of disk thrashing under low physical memory, or internal fragmentation in the final page of a block).
Question 13 · written
2 marks
A logic circuit has three inputs, \(A\), \(B\), and \(C\). The output \(X\) is represented by the Boolean expression:

\(X = (A \text{ NOR } B) \text{ XOR } (\text{NOT } C)\)

Determine the output value of \(X\) (0 or 1) for the following two sets of inputs:

1. \(A = 0, B = 0, C = 1\)
2. \(A = 1, B = 0, C = 1\)
Show answer & marking scheme

Worked solution

To find the output \(X\) for each set of inputs:

1. For \(A = 0, B = 0, C = 1\):
- First, evaluate the NOR term: \(A \text{ NOR } B = \text{NOT}(0 \text{ OR } 0) = \text{NOT}(0) = 1\).
- Next, evaluate the NOT term: \(\text{NOT } C = \text{NOT}(1) = 0\).
- Finally, evaluate the XOR: \(X = 1 \text{ XOR } 0 = 1\).

2. For \(A = 1, B = 0, C = 1\):
- First, evaluate the NOR term: \(A \text{ NOR } B = \text{NOT}(1 \text{ OR } 0) = \text{NOT}(1) = 0\).
- Next, evaluate the NOT term: \(\text{NOT } C = \text{NOT}(1) = 0\).
- Finally, evaluate the XOR: \(X = 0 \text{ XOR } 0 = 0\).

Marking scheme

Award 1 mark for each correct output value:
- 1 mark: \(X = 1\) for the first input set
- 1 mark: \(X = 0\) for the second input set
Question 14 · written
2 marks
A logic circuit has three inputs \(P\), \(Q\), and \(R\).

- Inputs \(P\) and \(Q\) are combined using an AND gate to produce an intermediate output \(W\).
- Input \(R\) is passed through a NOT gate to produce an intermediate output \(Y\).
- The intermediate outputs \(W\) and \(Y\) are combined using a NOR gate to produce the final output \(S\).

Write the Boolean expression for the output \(S\).
Show answer & marking scheme

Worked solution

We derive the expression step by step:
1. The intermediate output \(W\) is the output of the AND gate with inputs \(P\) and \(Q\):
\(W = P \text{ AND } Q\)

2. The intermediate output \(Y\) is the output of the NOT gate with input \(R\):
\(Y = \text{NOT } R\)

3. The final output \(S\) is the result of combining \(W\) and \(Y\) using a NOR gate:
\(S = W \text{ NOR } Y = (P \text{ AND } Q) \text{ NOR } (\text{NOT } R)\)

This can also be written in equivalent forms, such as:
\(S = \text{NOT}((P \text{ AND } Q) \text{ OR } (\text{NOT } R))\)

Marking scheme

Award marks as follows:
- 1 mark for correctly identifying the components: \((P \text{ AND } Q)\) and \(\text{NOT } R\).
- 1 mark for correctly combining both parts using the NOR operator (or the equivalent \(\text{NOT}(... \text{ OR } ...)\)).

Accept equivalent algebraic/Boolean notation, such as \(S = \overline{(P \cdot Q) + \overline{R}}\).
Question 15 · short_answer
4 marks
A database has a table Owner with a primary key OwnerID. Write an SQL DDL statement to create a table named Vehicle with the following fields and constraints:
- VehicleID: primary key, text of length 10
- Make: text of length 30
- Model: text of length 50
- YearOfManufacture: four-digit integer
- OwnerID: foreign key referencing the OwnerID field in the Owner table.
Show answer & marking scheme

Worked solution

To create a table in SQL, the CREATE TABLE statement is used. Each field is declared with an appropriate data type (VARCHAR/CHAR for text, INT/INTEGER for the year). The primary key is set on VehicleID, and the foreign key constraint is declared referencing Owner(OwnerID).

Marking scheme

1 mark: Correct CREATE TABLE Vehicle (...) syntax.
1 mark: VehicleID specified as primary key with correct type.
1 mark: Make, Model, and YearOfManufacture defined with appropriate types.
1 mark: OwnerID set as foreign key referencing Owner(OwnerID).
Question 16 · short_answer
4 marks
The database table Customer contains information about customers. Write SQL DDL statements to perform the following two structural changes:
1. Add a new field named EmailAddress to the Customer table, which can store text up to 100 characters.
2. Remove the existing field named MiddleName from the Customer table.
Show answer & marking scheme

Worked solution

The ALTER TABLE statement is used to modify the structure of an existing table. To add a column, ALTER TABLE Customer ADD is used followed by the column definition. To remove a column, ALTER TABLE Customer DROP COLUMN is used.

Marking scheme

1 mark: Correct use of ALTER TABLE Customer for adding a column.
1 mark: Correct syntax to add EmailAddress with VARCHAR(100) or CHAR(100).
1 mark: Correct use of ALTER TABLE Customer for dropping a column.
1 mark: Correct syntax to drop MiddleName (either DROP COLUMN MiddleName or DROP MiddleName).
Question 17 · short_answer
4 marks
A database has two tables:
Student (StudentID, FirstName, LastName, ClassID)
Class (ClassID, ClassName, RoomNumber)

Write an SQL query to display the FirstName and LastName of all students, and the ClassName of their class, for all classes located in RoomNumber 'A12'.
Show answer & marking scheme

Worked solution

The query requires a join operation between the Student and Class tables on the matching ClassID fields. The SELECT clause lists the requested fields, and the WHERE clause filters the results for RoomNumber 'A12'.

Marking scheme

1 mark: Correct SELECT clause with FirstName, LastName, and ClassName.
1 mark: Correct FROM clause specifying both tables (Student and Class).
1 mark: Correct join condition matching ClassID between both tables (either using INNER JOIN ... ON or WHERE).
1 mark: Correct filter WHERE RoomNumber = 'A12'.
Question 18 · short_answer
4 marks
A database contains a table named Product which has the attributes ProductID, ProductName, UnitPrice, and StockLevel.

Write SQL statements to perform the following two tasks:
1. Increase the UnitPrice by 10% for all products where the StockLevel is less than 10.
2. Delete all records from the Product table where the StockLevel is exactly 0.
Show answer & marking scheme

Worked solution

For task 1, an UPDATE query is used with SET to modify the UnitPrice and a WHERE clause to filter the products. For task 2, a DELETE FROM statement is used with a WHERE clause to select products with a StockLevel of 0.

Marking scheme

1 mark: Correct UPDATE Product SET UnitPrice = UnitPrice * 1.1 (or equivalent expression).
1 mark: Correct WHERE StockLevel < 10 for the UPDATE statement.
1 mark: Correct DELETE FROM Product syntax.
1 mark: Correct WHERE StockLevel = 0 for the DELETE statement.
Question 19 · text
3.6 marks
A processor's instruction set includes the following assembly instructions: [LDM #n] Load the number n to ACC; [LDD ] Load the contents of the given address to ACC; [LDR IX, #n] Load index register IX with immediate value n; [LDX ] Load the contents of the address (address + IX) to ACC; [STO ] Store the contents of ACC to the given address; [STX ] Store the contents of ACC to the address (address + IX); [ADD ] Add the contents of the given address to ACC; [DEC ACC] Decrement ACC by 1. The initial memory values are: Address 100 = 0, Address 105 = 12, Address 106 = 15, Address 107 = 18, Address 110 = 0, Address 111 = 30, Address 112 = 35. The following assembly program is executed: LDM #4 | STO 100 | LDR IX, #2 | LDX 105 | ADD 100 | STX 110 | LDD 111 | DEC ACC | STO 111. Determine the final value stored in memory address 112.
Show answer & marking scheme

Worked solution

Step-by-step trace: 1) LDM #4 sets ACC to 4. 2) STO 100 stores 4 in address 100. 3) LDR IX, #2 sets IX to 2. 4) LDX 105 loads value from address (105 + IX) which is 107. Since address 107 has 18, ACC becomes 18. 5) ADD 100 adds the value at address 100 (which is 4) to ACC, so ACC = 22. 6) STX 110 stores ACC (22) at address (110 + IX) which is 112. Thus, address 112 gets the value 22. 7) LDD 111 loads value from address 111 (30) to ACC. 8) DEC ACC decrements ACC to 29. 9) STO 111 stores 29 in address 111. The final value in address 112 is 22.

Marking scheme

1 mark for finding index register IX = 2 and loading 18 from address 107. 1 mark for adding value at address 100 (4) to get ACC = 22. 1 mark for storing 22 at target address 112 using indexed addressing. 0.6 marks for accurate final value 22.
Question 20 · text
3.6 marks
A processor's instruction set includes the following assembly instructions: [LDD ] Load the contents of the given address to ACC; [LDI ] Indirect addressing (Load ACC with contents of the address found at the given address); [STO ] Store the contents of ACC to the given address; [ADD ] Add the contents of the given address to ACC; [SUB #n] Subtract immediate value n from ACC; [CMP #n] Compare ACC with immediate value n; [JPE ] Jump to label if preceding comparison was equal. The initial memory values are: Address 200 = 203, Address 201 = 204, Address 202 = 5, Address 203 = 14, Address 204 = 25, Address 205 = 50. The following assembly program is executed: LDD 202 | CMP #5 | JPE L1 | LDD 200 | L1: LDI 200 | ADD 202 | STO 205 | LDI 201 | SUB #10 | STO 204. Determine the final value stored in memory address 204.
Show answer & marking scheme

Worked solution

Step-by-step trace: 1) LDD 202 loads 5 into ACC. 2) CMP #5 compares ACC (5) with 5, setting the equal status. 3) JPE L1 branches to label L1, bypassing LDD 200. 4) L1: LDI 200 performs an indirect load. Address 200 contains 203, so it loads from address 203. Since address 203 contains 14, ACC becomes 14. 5) ADD 202 adds the value at address 202 (5) to ACC, making ACC = 19. 6) STO 205 stores 19 in address 205. 7) LDI 201 performs an indirect load. Address 201 contains 204, so it loads from address 204. Since address 204 contains 25, ACC becomes 25. 8) SUB #10 subtracts 10 from ACC, making ACC = 15. 9) STO 204 stores 15 in address 204. The final value in address 204 is 15.

Marking scheme

1 mark for identifying the conditional jump is taken, bypassing LDD 200. 1 mark for evaluating the indirect load LDI 200 as loading 14 and storing 19 in address 205. 1 mark for evaluating LDI 201 as loading 25, subtracting 10 to get 15. 0.6 marks for final accurate value 15 in address 204.
Question 21 · text
3.6 marks
A processor's instruction set includes the following assembly instructions: [LDM #n] Load the number n to ACC; [LDD ] Load the contents of the given address to ACC; [LDR IX, #n] Load index register IX with immediate value n; [LDX ] Load the contents of the address (address + IX) to ACC; [STO ] Store the contents of ACC to the given address; [ADD ] Add the contents of the given address to ACC; [DEC ACC] Decrement ACC by 1; [INC IX] Increment index register IX by 1; [CMP #n] Compare ACC with immediate value n; [JPN ] Jump to label if preceding comparison was not equal. The initial memory values are: Address 80 = 3, Address 81 = 10, Address 82 = 20, Address 83 = 30, Address 84 = 40, Address 85 = 0. The following assembly program is executed: LDR IX, #0 | LDM #0 | STO 85 | LOOP: LDX 81 | ADD 85 | STO 85 | INC IX | LDD 80 | DEC ACC | STO 80 | CMP #0 | JPN LOOP. Determine the final value stored in memory address 85 after the program completes execution.
Show answer & marking scheme

Worked solution

Step-by-step trace of the loop: Initial states are IX = 0, Memory[85] = 0, Memory[80] = 3. Iteration 1: LDX 81 loads Memory[81+0] = 10. ADD 85 adds 0, ACC = 10. STO 85 stores 10 in 85. INC IX increments IX to 1. LDD 80 loads 3, DEC ACC decrements to 2, STO 80 stores 2 in 80. CMP #0 checks 2, JPN LOOP jumps back. Iteration 2: LDX 81 loads Memory[81+1] = 20. ADD 85 adds 10, ACC = 30. STO 85 stores 30 in 85. INC IX increments IX to 2. LDD 80 loads 2, DEC ACC decrements to 1, STO 80 stores 1 in 80. CMP #0 checks 1, JPN LOOP jumps back. Iteration 3: LDX 81 loads Memory[81+2] = 30. ADD 85 adds 30, ACC = 60. STO 85 stores 60 in 85. INC IX increments IX to 3. LDD 80 loads 1, DEC ACC decrements to 0, STO 80 stores 0 in 80. CMP #0 checks 0, comparison is equal so JPN LOOP is not taken. The loop terminates. The final value in address 85 is 60.

Marking scheme

1 mark for tracing the loop counter decrementing from 3 down to 0 over 3 iterations. 1 mark for tracing the index register incrementing from 0 to 3. 1 mark for accumulating the correct values (10 + 20 + 30) to get 60. 0.6 marks for final accurate value 60 stored in address 85.

Paper 2 Fundamental Problem-solving and Programming Skills

Answer all questions. Refer to the insert for pseudocode helper functions.
12 Question · 63.79999999999999 marks
Question 1 · practical
3.5 marks
Consider the following pseudocode algorithm that processes a 1D array of integers:

```pseudocode
PROCEDURE Analyse(BYREF Data : ARRAY[1..6] OF INTEGER)
DECLARE x, y, temp : INTEGER
x <- 1
y <- 6
WHILE x < y DO
IF Data[x] > Data[y] THEN
temp <- Data[x]
Data[x] <- Data[y]
Data[y] <- temp
x <- x + 1
ELSE
y <- y - 1
ENDIF
ENDWHILE
ENDPROCEDURE
```

The array `Data` initially contains the following elements:
- `Data[1] = 12`
- `Data[2] = 5`
- `Data[3] = 8`
- `Data[4] = 14`
- `Data[5] = 3`
- `Data[6] = 9`

Complete the dry run table for the procedure call `Analyse(Data)` by writing the successive values of variables `x`, `y`, `temp` and the array `Data`. Only write values when they change. The initial values for the array have been provided in the first row.
Show answer & marking scheme

Worked solution

Let's trace the algorithm step-by-step:
1. Initial state: `x = 1`, `y = 6`, `Data = [12, 5, 8, 14, 3, 9]`.
2. **Iteration 1**: `x < y` (1 < 6) is TRUE. `Data[1] > Data[6]` (12 > 9) is TRUE.
- `temp <- Data[1]` (12)
- `Data[1] <- Data[6]` (9)
- `Data[6] <- temp` (12)
- `x <- x + 1` (2)
- `Data` is now `[9, 5, 8, 14, 3, 12]`.
3. **Iteration 2**: `x < y` (2 < 6) is TRUE. `Data[2] > Data[6]` (5 > 12) is FALSE.
- `y <- y - 1` (5)
4. **Iteration 3**: `x < y` (2 < 5) is TRUE. `Data[2] > Data[5]` (5 > 3) is TRUE.
- `temp <- Data[2]` (5)
- `Data[2] <- Data[5]` (3)
- `Data[5] <- temp` (5)
- `x <- x + 1` (3)
- `Data` is now `[9, 3, 8, 14, 5, 12]`.
5. **Iteration 4**: `x < y` (3 < 5) is TRUE. `Data[3] > Data[5]` (8 > 5) is TRUE.
- `temp <- Data[3]` (8)
- `Data[3] <- Data[5]` (5)
- `Data[5] <- temp` (8)
- `x <- x + 1` (4)
- `Data` is now `[9, 3, 5, 14, 8, 12]`.
6. **Iteration 5**: `x < y` (4 < 5) is TRUE. `Data[4] > Data[5]` (14 > 8) is TRUE.
- `temp <- Data[4]` (14)
- `Data[4] <- Data[5]` (8)
- `Data[5] <- temp` (14)
- `x <- x + 1` (5)
- `Data` is now `[9, 3, 5, 8, 14, 12]`.
7. **Iteration 6**: `x < y` (5 < 5) is FALSE. Loop terminates.

Marking scheme

Max 3.5 marks:
- 1 mark: Correctly identifying when to decrement `y` to 5 and leave elements unchanged when the comparison `Data[2] > Data[6]` (5 > 12) is False.
- 1 mark: Correct array elements swaps for `Data[1]` and `Data[6]`, as well as `Data[2]` and `Data[5]` along with their corresponding updates to `temp` and `x`.
- 1 mark: Correct array elements swaps for `Data[3]` and `Data[5]`, as well as `Data[4]` and `Data[5]` along with their corresponding updates to `temp` and `x`.
- 0.5 marks: Correctly updating loop variables `x` and `y` to final state values of 5 and 5 with proper loop termination.
Question 2 · practical
3.5 marks
The recursive function `Recurse` is defined as follows:

```pseudocode
FUNCTION Recurse(a : INTEGER, b : INTEGER) RETURNS INTEGER
IF a <= 0 OR b <= 0 THEN
RETURN 1
ELSEIF a > b THEN
RETURN b + Recurse(a - b, b)
ELSE
RETURN a + Recurse(a, b - a)
ENDIF
ENDFUNCTION
```

Trace the execution of the function call `Recurse(4, 3)`. Show each recursive call with its respective parameter values and state the final returned value.
Show answer & marking scheme

Worked solution

Let us trace the recursion step-by-step:
- **Call 1**: `Recurse(4, 3)`. Since `a > b` (4 > 3), the `ELSEIF` condition triggers, returning `3 + Recurse(1, 3)`.
- **Call 2**: `Recurse(1, 3)`. Since `a > b` is false (1 > 3 is false) and neither is <= 0, the `ELSE` condition triggers, returning `1 + Recurse(1, 2)`.
- **Call 3**: `Recurse(1, 2)`. Similarly, since `1 > 2` is false, this returns `1 + Recurse(1, 1)`.
- **Call 4**: `Recurse(1, 1)`. Since `1 > 1` is false, this returns `1 + Recurse(1, 0)`.
- **Call 5**: `Recurse(1, 0)`. Since `b <= 0` (0 <= 0 is true), the base case triggers, returning `1`.

Working back up the call stack:
- `Recurse(1, 1)` returns `1 + 1 = 2`.
- `Recurse(1, 2)` returns `1 + 2 = 3`.
- `Recurse(1, 3)` returns `1 + 3 = 4`.
- `Recurse(4, 3)` returns `3 + 4 = 7`.

Marking scheme

Max 3.5 marks:
- 1 mark: Correctly demonstrating the base case parameter triggering (`b = 0`) and returning 1.
- 1 mark: Correct parameter transitions sequence through recursive calls: (4, 3) -> (1, 3) -> (1, 2) -> (1, 1) -> (1, 0).
- 1 mark: Correctly representing the accumulation logic working up the stack (+3 for the first call, +1 for others).
- 0.5 marks: Correct final return value of 7.
Question 3 · practical
3.5 marks
Consider the following pseudocode function that processes a string:

```pseudocode
FUNCTION Compress(Str : STRING) RETURNS STRING
DECLARE OutStr : STRING
DECLARE Count, i : INTEGER
DECLARE CurrentChar : CHAR

IF LENGTH(Str) = 0 THEN
RETURN ""
ENDIF

OutStr <- ""
CurrentChar <- MID(Str, 1, 1)
Count <- 1

FOR i <- 2 TO LENGTH(Str)
IF MID(Str, i, 1) = CurrentChar THEN
Count <- Count + 1
ELSE
OutStr <- OutStr & CurrentChar & NUM_TO_STR(Count)
CurrentChar <- MID(Str, i, 1)
Count <- 1
ENDIF
ENDFOR

OutStr <- OutStr & CurrentChar & NUM_TO_STR(Count)
RETURN OutStr
ENDFUNCTION
```

Complete the dry run table for the function call `Compress("AAABBC")`. Write values only when they change.
Show answer & marking scheme

Worked solution

Let's trace the function execution with `Str = "AAABBC"`:
1. Initial state before loop: `OutStr = ""`, `CurrentChar = "A"`, `Count = 1`.
2. **i = 2**: `MID(Str, 2, 1)` is `"A"`. This matches `CurrentChar`, so `Count <- Count + 1` which is 2.
3. **i = 3**: `MID(Str, 3, 1)` is `"A"`. This matches `CurrentChar`, so `Count <- Count + 1` which is 3.
4. **i = 4**: `MID(Str, 4, 1)` is `"B"`. This does NOT match `CurrentChar`. Thus, `OutStr <- OutStr & CurrentChar & NUM_TO_STR(Count)` which results in `"" & "A" & "3" = "A3"`. `CurrentChar` is updated to `"B"`, and `Count` is reset to 1.
5. **i = 5**: `MID(Str, 5, 1)` is `"B"`. This matches `CurrentChar`, so `Count <- Count + 1` which is 2.
6. **i = 6**: `MID(Str, 6, 1)` is `"C"`. This does NOT match `CurrentChar`. Thus, `OutStr <- OutStr & CurrentChar & NUM_TO_STR(Count)` which results in `"A3" & "B" & "2" = "A3B2"`. `CurrentChar` is updated to `"C"`, and `Count` is reset to 1.
7. Loop ends.
8. After the loop, the remaining character is appended: `OutStr <- OutStr & CurrentChar & NUM_TO_STR(Count)`, yielding `"A3B2" & "C" & "1" = "A3B2C1"`.
9. Returns `"A3B2C1"`.

Marking scheme

Max 3.5 marks:
- 1 mark: Correctly tracking variable values for the first run (until `i = 3` with `Count = 3`).
- 1 mark: Correct transition logic at `i = 4` (concatenation to `OutStr`, setting `CurrentChar` to `"B"`, and resetting `Count` to 1).
- 1 mark: Correct transition logic at `i = 6` (concatenation to `OutStr`, setting `CurrentChar` to `"C"`, and resetting `Count` to 1).
- 0.5 marks: Correctly executing post-loop code to yield the final returned value of `"A3B2C1"`.
Question 4 · practical
3.5 marks
A 2D array `Grid` of size 3x3 is populated with the following integer values:
- Row 1: 3, 5, 7
- Row 2: 1, 4, 6
- Row 3: 9, 2, 3

Complete the dry run table for the procedure call `ProcessGrid(Grid)`. Use the variables: `Row`, `Col`, `Check`, `Sum`, and `OUTPUT`. Write values only when they change.

```pseudocode
PROCEDURE ProcessGrid(Grid : ARRAY[1..3, 1..3] OF INTEGER)
DECLARE Row, Col, Sum : INTEGER
DECLARE Check : BOOLEAN
Sum <- 0
FOR Row <- 1 TO 3
Check <- TRUE
FOR Col <- 1 TO 3
IF Grid[Row, Col] MOD 2 = 0 THEN
Sum <- Sum + Grid[Row, Col]
Check <- FALSE
ENDIF
ENDFOR
IF Check = TRUE THEN
Sum <- Sum + 10
ENDIF
ENDFOR
OUTPUT Sum
ENDPROCEDURE
```
Show answer & marking scheme

Worked solution

Step-by-step trace:
- `Sum` is initialized to 0.
- **Row = 1**:
- `Check` is set to `TRUE`.
- `Col = 1`: `Grid[1, 1]` is 3 (odd). No match.
- `Col = 2`: `Grid[1, 2]` is 5 (odd). No match.
- `Col = 3`: `Grid[1, 3]` is 7 (odd). No match.
- Loop ends. `Check` is `TRUE`, so `Sum <- Sum + 10` which becomes 10.
- **Row = 2**:
- `Check` is set to `TRUE`.
- `Col = 1`: `Grid[2, 1]` is 1 (odd). No match.
- `Col = 2`: `Grid[2, 2]` is 4 (even). `Sum <- Sum + 4` (14), `Check <- FALSE`.
- `Col = 3`: `Grid[2, 3]` is 6 (even). `Sum <- Sum + 6` (20).
- Loop ends. `Check` is `FALSE`, so no addition of 10.
- **Row = 3**:
- `Check` is set to `TRUE`.
- `Col = 1`: `Grid[3, 1]` is 9 (odd). No match.
- `Col = 2`: `Grid[3, 2]` is 2 (even). `Sum <- Sum + 2` (22), `Check <- FALSE`.
- `Col = 3`: `Grid[3, 3]` is 3 (odd). No match.
- Loop ends. `Check` is `FALSE`, so no addition of 10.
- Output `Sum` which is 22.

Marking scheme

Max 3.5 marks:
- 1 mark: Correctly tracing `Row = 1` actions including `Check` remaining `TRUE` and adding 10 to `Sum`.
- 1 mark: Correctly tracing `Row = 2` including updating `Check` to `FALSE` and adding even values (4 and 6) to `Sum`.
- 1 mark: Correctly tracing `Row = 3` including updating `Check` to `FALSE` and adding even value (2) to `Sum`.
- 0.5 marks: Correctly demonstrating the final output instruction with value 22.
Question 5 · written
4.5 marks
In a software design, a structure chart shows that a control module 'ProcessRegistration' calls a sub-module 'ValidateDetails'. The interfaces between these modules are represented by: 1) A data couple 'StudentID' of type String passing from 'ProcessRegistration' to 'ValidateDetails'. 2) A data couple 'EmailAddress' of type String passing from 'ProcessRegistration' to 'ValidateDetails'. 3) A control flag 'IsValid' of type Boolean passing back from 'ValidateDetails' to 'ProcessRegistration'. Write the pseudocode module header for 'ValidateDetails' as a function.
Show answer & marking scheme

Worked solution

To translate the structure chart interfaces into a pseudocode function header: 1. Identify the module type as a FUNCTION because it returns a single control flag parameter ('IsValid' of type Boolean). 2. Define the parameters passing into the module as 'StudentID' and 'EmailAddress', both of type STRING. 3. State the return type of the function as BOOLEAN. The final pseudocode header is: FUNCTION ValidateDetails(StudentID : STRING, EmailAddress : STRING) RETURNS BOOLEAN

Marking scheme

1 mark: Correct use of keyword FUNCTION and matching name ValidateDetails. 2 marks: Correct parameters with types (StudentID : STRING, EmailAddress : STRING) (1 mark for each parameter). 1.5 marks: Correct return type definition (RETURNS BOOLEAN).
Question 6 · written
4.5 marks
An automated turnstile system has three states: Locked, Unlocked, and Alarm. The system starts in the Locked state. If a user inserts a valid coin ('coin'), the system transitions to the Unlocked state. If a user pushes the turnstile ('push') while in the Unlocked state, it transitions back to the Locked state. If the turnstile is forced open ('force') while in the Locked state, it transitions to the Alarm state. A manual security override ('reset') transitions the system from the Alarm state back to the Locked state. Construct the state transition table for this system by listing all valid transitions in the format: [Current State] + [Event] -> [Next State].
Show answer & marking scheme

Worked solution

The state transitions derived from the system rules are: 1. Locked state with event 'coin' goes to Unlocked state. 2. Unlocked state with event 'push' goes to Locked state. 3. Locked state with event 'force' goes to Alarm state. 4. Alarm state with event 'reset' goes to Locked state.

Marking scheme

1 mark: For transition Locked + coin -> Unlocked. 1 mark: For transition Unlocked + push -> Locked. 1 mark: For transition Locked + force -> Alarm. 1 mark: For transition Alarm + reset -> Locked. 0.5 marks: For clearly indicating Locked as the starting/initial state.
Question 7 · Syllabus Pseudocode Writing
6.8 marks
A text file, `Scores.txt`, contains records of students and their test scores. Each record consists of exactly two consecutive lines in the file:
1. The student's name (STRING)
2. The student's score (INTEGER)

Write pseudocode for a function `CountAndSavePasses(MinPassScore : INTEGER) RETURNS INTEGER`. This function must:
- Read all records from the file `Scores.txt`.
- Identify students who have a score greater than or equal to `MinPassScore`.
- Write the names of these passing students to a new text file named `Passes.txt`, with each name on a new line.
- Count the total number of passing students.
- Close both files and return this total count.
Show answer & marking scheme

Worked solution

The function begins by declaring the local variables and initializing the count variable to 0. It opens 'Scores.txt' in READ mode and 'Passes.txt' in WRITE mode. A loop is executed until the end of the input file is reached. Inside the loop, it reads two consecutive lines corresponding to the name and the score. It then checks if the score is greater than or equal to the minimum passing score. If true, the name is written to 'Passes.txt' and the counter is incremented. Finally, both files are closed and the counter is returned.

Marking scheme

1 mark: Correct function header and return type definition.
1 mark: Declaring local variables with correct data types.
1 mark: Opening 'Scores.txt' for reading and 'Passes.txt' for writing.
1 mark: Implementing a loop that runs until EOF of 'Scores.txt' is reached.
1 mark: Reading both values (name and score) in the correct order inside the loop.
1 mark: Correct conditional statement to check if the score is >= MinPassScore.
1 mark: Writing names of passing students to 'Passes.txt' and updating the count.
1 mark: Closing both files and returning the correct count value.
Question 8 · Syllabus Pseudocode Writing
6.8 marks
A 2D array, `Matrix`, is declared globally as:
`DECLARE Matrix : ARRAY[1:5, 1:5] OF INTEGER`

Write pseudocode for a function `SumDiagonalDiff() RETURNS INTEGER` that computes and returns the absolute difference between the sum of the elements on the primary diagonal (from top-left `Matrix[1,1]` to bottom-right `Matrix[5,5]`) and the sum of the elements on the secondary diagonal (from top-right `Matrix[1,5]` to bottom-left `Matrix[5,1]`).

Do not use any built-in absolute value function; implement the absolute difference logic directly.
Show answer & marking scheme

Worked solution

The function initialises variables for the primary and secondary diagonal sums. Using a single loop running from 1 to 5, it accumulates the diagonal values. The primary diagonal element at step I is at index [I, I]. The secondary diagonal element is at index [I, 6 - I]. After the loop, the difference is calculated. If the difference is negative, it is multiplied by -1 to get the absolute value, which is then returned.

Marking scheme

1 mark: Correct function header and return type integer.
1 mark: Declaring and initializing PrimarySum and SecondarySum to 0.
1 mark: Correct loop running exactly from 1 to 5.
2 marks: Correct array index mapping for primary diagonal (Matrix[I, I]) and secondary diagonal (Matrix[I, 6 - I]).
1 mark: Logic to calculate absolute value without standard library functions.
1 mark: Returning the final computed absolute difference.
Question 9 · Syllabus Pseudocode Writing
6.8 marks
Write a recursive pseudocode function `SumEven(N : INTEGER) RETURNS INTEGER` that returns the sum of all positive even integers from 2 up to N (inclusive).

The function must follow these rules:
- If N is less than 2, the function must return 0.
- If N is odd, the function must recursively call itself with N - 1.
- If N is even and greater than or equal to 2, the function must return the sum of N and a recursive call with N - 2.
Show answer & marking scheme

Worked solution

The function first checks the base case: if N is less than 2, it returns 0. If N is odd (checked using the expression N MOD 2 <> 0), it recursively calls itself with N - 1 to convert the problem into an even boundary. If N is even, it performs the recursive step of adding N to the result of SumEven(N - 2).

Marking scheme

1 mark: Correct function header with correct parameter name, type, and return type.
2 marks: Base case correctly checking if N < 2 and returning 0.
2 marks: Recursive case for odd values of N calling SumEven(N - 1).
2 marks: Recursive case for even values of N returning N + SumEven(N - 2).
Question 10 · Syllabus Pseudocode Writing
6.8 marks
A circular queue is implemented using a global array `QueueData[1:10] OF STRING` and three global integer variables:
- `HeadPointer` (stores the index of the first item in the queue)
- `TailPointer` (stores the index of the last item in the queue)
- `NumItems` (stores the current number of items in the queue)

Write a pseudocode procedure `Enqueue(NewItem : STRING)` to insert an item into the queue. The procedure must check if the queue is full and output "Queue Full" if it is. If the queue is empty, the first item must be added at index 1. Ensure the index wraps around to 1 if it exceeds 10.
Show answer & marking scheme

Worked solution

The procedure first checks if the queue is already full by checking if NumItems is equal to 10. If so, it outputs "Queue Full". If the queue is empty (NumItems is 0), both HeadPointer and TailPointer are set to 1. Otherwise, TailPointer is incremented. If TailPointer exceeds 10, it wraps around to 1. Finally, NewItem is placed at QueueData[TailPointer] and NumItems is incremented.

Marking scheme

1 mark: Correct procedure header with parameter declaration.
1 mark: Checking if queue is full (NumItems = 10) and outputting message.
1 mark: Logic to handle initial insertion when queue is empty.
2 marks: Logic to increment and wrap TailPointer using IF TailPointer > 10 THEN TailPointer <- 1.
1 mark: Assigning NewItem to QueueData[TailPointer].
1 mark: Incrementing NumItems after successful insertion.
Question 11 · Syllabus Pseudocode Writing
6.8 marks
Write pseudocode for a function `ValidatePassword(Password : STRING) RETURNS BOOLEAN`. The function must validate that the parameter `Password` meets the following criteria:
1. Total length is between 6 and 12 characters inclusive.
2. Contains at least one uppercase letter ('A' to 'Z').
3. Contains at least one lowercase letter ('a' to 'z').

You should use these built-in functions:
- `LENGTH(S : STRING) RETURNS INTEGER`
- `MID(S : STRING, Start : INTEGER, Length : INTEGER) RETURNS STRING`
Show answer & marking scheme

Worked solution

The function validates the password structure. First, it extracts the length and returns FALSE if it is outside the range [6, 12]. Next, it loops through each character of the password using the MID function. It updates boolean flags if uppercase or lowercase letters are found. Finally, it returns TRUE if both flags are true, otherwise FALSE.

Marking scheme

1 mark: Correct function header and return type definition.
1 mark: Correct length check validation using OR or logical limits returning FALSE.
1 mark: Initializing boolean flags for upper and lower check to FALSE.
1 mark: Using loop from 1 to LENGTH(Password) and accessing each character using MID.
1 mark: Checking for uppercase range correctly.
1 mark: Checking for lowercase range correctly.
1 mark: Returning TRUE only if both conditions are met, otherwise FALSE.
Question 12 · Syllabus Pseudocode Writing
6.8 marks
Write pseudocode for a procedure `BubbleSortDescending(BYREF Numbers : ARRAY OF INTEGER, Size : INTEGER)`. The procedure must sort the 1D array `Numbers` containing `Size` integers in descending order using the bubble sort algorithm.

To optimize the procedure, use a boolean flag `Swapped` to stop the sorting process early if a complete pass occurs with no elements being swapped.
Show answer & marking scheme

Worked solution

The procedure implements an optimized bubble sort in descending order. The outer loop is a post-condition loop (REPEAT...UNTIL) controlled by a boolean flag `Swapped` and an iteration count `Pass`. In each pass, the inner loop compares adjacent elements. Since we want a descending order, we swap them if the left element `Numbers[I]` is smaller than the right element `Numbers[I+1]`. If any swap occurs, `Swapped` is set to TRUE. The process terminates if no elements were swapped on a complete pass.

Marking scheme

1 mark: Correct procedure header with parameter declarations (BYREF array, BYVAL size).
1 mark: Initializing Pass counter and outer loop structure.
1 mark: Resetting Swapped flag to FALSE at start of outer loop.
1 mark: Correct inner loop limit (1 TO Size - Pass).
1 mark: Correct descending comparison (Numbers[I] < Numbers[I + 1]).
1 mark: Swapping elements correctly using a temporary variable and setting Swapped to TRUE.
1 mark: Correct loop termination condition when NOT Swapped.

Paper 3 Advanced Theory

Answer all questions on the exam paper.
17 Question · 60 marks
Question 1 · structural
3 marks
A computer system represents real numbers using a 12-bit normalized floating-point representation in two's complement. The mantissa is 8 bits and the exponent is 4 bits.

Convert the denary value \(-6.75\) into this representation. Show your working.
Show answer & marking scheme

Worked solution

1. Convert the absolute value of the number to binary:
\(6.75 = 6 + 0.75 = 110_2 + 0.11_2 = 110.11_2\)

2. To represent the negative value \(-6.75\), write \(+6.75\) with leading zero bits (e.g., \(0110.1100\)) and take the two's complement:
- Invert the bits: \(1001.0011\)
- Add 1: \(1001.0100_2\) (which represents \(-6.75\))

3. Normalize this negative number. A normalized negative floating-point number must start with the bits \(10\):
\(1.0010100_2 \times 2^3\)

4. Write down the 8-bit mantissa:
Mantissa = \(10010100\)

5. Write down the 4-bit exponent for \(+3\) in two's complement:
\(3 = 0011_2\)
Exponent = \(0011\)

Combined 12-bit representation: \(10010100\ 0011\)

Marking scheme

1 mark for converting \(6.75\) or \(-6.75\) correctly to binary (e.g. \(1001.01\)).
1 mark for normalizing the negative mantissa correctly to 8 bits: \(10010100\).
1 mark for the correct 4-bit exponent: \(0011\).
Question 2 · structural
3 marks
A floating-point representation stores real numbers using an 8-bit normalized mantissa and a 4-bit exponent, both in two's complement.

Calculate the denary value of the following floating-point representation:
- Mantissa: `01011000`
- Exponent: `1101`

Show your working.
Show answer & marking scheme

Worked solution

1. Analyze the mantissa:
- The mantissa is `01011000`. Since it begins with `0`, it represents a positive number.
- Placing the binary point after the first bit (sign bit): \(0.1011000_2\)
- Convert to denary: \(0.5 \times 1 + 0.25 \times 0 + 0.125 \times 1 + 0.0625 \times 1 = 0.5 + 0.125 + 0.0625 = 0.6875\) (or \(\frac{11}{16}\))

2. Analyze the exponent:
- The exponent is `1101`. Since it begins with `1`, it is a negative number represented in two's complement.
- Convert `1101` to denary: \(-8 + 4 + 1 = -3\) (or invert `1101` \(\rightarrow\) `0010`, add 1 \(\rightarrow\) `0011`, giving \(-3\))

3. Calculate the final value:
- Value = \(0.6875 \times 2^{-3} = 0.6875 \times \frac{1}{8} = 0.0859375\) (or \(\frac{11}{128}\))

Marking scheme

1 mark for calculating the correct mantissa value (\(0.6875\) or \(\frac{11}{16}\)).
1 mark for calculating the correct exponent value (\(-3\)).
1 mark for calculating the correct final denary value (\(0.0859375\) or \(\frac{11}{128}\)).
Question 3 · structural
3 marks
In floating-point representations, underflow can occur during arithmetic operations.

Describe what is meant by underflow in this context, and explain how a computer system may handle a number that has underflowed.
Show answer & marking scheme

Worked solution

1. Underflow occurs when an arithmetic operation results in a non-zero value that is too small (its absolute value is too close to zero) to be represented with the minimum possible exponent allocated in the system.
2. This happens because the negative exponent required to represent the actual value is smaller (more negative) than the range of the exponent bits allows.
3. Computer systems typically handle underflow by representing the value as zero (known as 'flush-to-zero') or by raising an underflow exception / setting a status flag.

Marking scheme

1 mark for stating that the value is too small to be represented (or magnitude is smaller than the minimum representable non-zero value).
1 mark for explaining that this is because the negative exponent required is beyond the capacity of the allocated exponent bits.
1 mark for identifying that the system represents the result as zero (or raises an exception/error flag).
Question 4 · structural
3 marks
A digital logic circuit is designed with three inputs, \(A\), \(B\), and \(C\). The output of the circuit is represented by the following truth table:

| A | B | C | Output |
|---|---|---|--------|
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 |
| 1 | 1 | 1 | 0 |

Using a Karnaugh Map (K-map) or algebraic simplification, derive the simplified sum-of-products (SOP) boolean expression for the output.
Show answer & marking scheme

Worked solution

1. Construct the K-map from the truth table:

```
BC
A | 00 | 01 | 11 | 10
----+----+----+----+----
0 | 0 | 1 | 1 | 0
1 | 1 | 1 | 0 | 0
```

2. Group the adjacent 1s to form the largest possible groups (each containing a power of 2 cells):
- **Group 1**: Cells (0,0,1) and (0,1,1) in the first row. This group spans across \(B=0\) and \(B=1\), which cancels out \(B\). Since \(A=0\) and \(C=1\), this simplifies to \(\bar{A}C\).
- **Group 2**: Cells (1,0,0) and (1,0,1) in the second row. This group spans across \(C=0\) and \(C=1\), which cancels out \(C\). Since \(A=1\) and \(B=0\), this simplifies to \(A\bar{B}\).

3. Combine both simplified terms to obtain the final sum-of-products boolean expression:
\(A\bar{B} + \bar{A}C\)

Marking scheme

1 mark for correctly placing the 1s in the K-map (or identifying the four active minterms).
1 mark for grouping and simplifying the first loop to \(\bar{A}C\).
1 mark for grouping and simplifying the second loop to \(A\bar{B}\) and providing the final sum-of-products expression.
Question 5 · structural
3 marks
Explain why some denary real numbers, such as \(0.1\), cannot be represented exactly in binary floating-point systems, and explain how this leads to issues when performing repetitive additions of such numbers in a loop.
Show answer & marking scheme

Worked solution

1. Many denary fractional numbers like \(0.1\) cannot be represented exactly in binary because they do not have a finite representation as a sum of powers of 2 (i.e., they form a recurring/infinite binary fraction: \(0.0001100110011..._2\)).
2. Because the mantissa has a fixed number of bits, the number must be rounded or truncated, introducing a small rounding/quantization error.
3. When performing repetitive additions of this value (e.g., in a loop), these small errors accumulate (cumulative error). For example, a loop intended to run until a variable exactly equals \(1.0\) may never terminate because the accumulated sum might skip the exact value due to precision limits.

Marking scheme

1 mark for explaining that \(0.1\) has a recurring binary representation / cannot be expressed as a finite sum of powers of 2.
1 mark for stating that rounding/truncating to fit the fixed mantissa size introduces an initial representation error.
1 mark for explaining that repetitive additions cause these errors to accumulate, leading to significant inaccuracies or infinite/malfunctioning loops.
Question 6 · Architecture Explanations & Protocols
4 marks
In computer architectures that use pipelining, hazards can disrupt the instruction cycle. Explain what is meant by a data dependency hazard in a pipelined processor, and describe how operand forwarding (bypassing) resolves this hazard without stalling the pipeline.
Show answer & marking scheme

Worked solution

A data dependency hazard arises during instruction pipelining when instruction N+1 requires data from instruction N, but instruction N has not yet completed its write-back stage. Normally, this would require a pipeline stall (bubble) where instruction N+1 is held. Operand forwarding resolves this by adding hardware paths that detect this dependency and copy the output buffer of the ALU (or executive phase) directly to the input of the ALU for the next clock cycle, bypassing the register write-back and read phases entirely. This allows execution to proceed at full speed without needing to insert stall cycles.

Marking scheme

1 mark: Definition of data dependency hazard (one instruction relies on output of previous instruction not yet written back). 1 mark: Identification that without intervention, this leads to a pipeline stall/bubble. 1 mark: Explanation of forwarding (routing data directly from ALU output of the producer instruction). 1 mark: Explanation of routing to ALU input of the consumer instruction, bypassing register write-back/read.
Question 7 · Architecture Explanations & Protocols
4 marks
Virtual machines (VMs) rely on hypervisors to run multiple guest operating systems. Compare Type 1 (bare-metal) and Type 2 (hosted) hypervisors by describing their positions in the system software stack and explaining one advantage of a Type 1 hypervisor.
Show answer & marking scheme

Worked solution

A Type 1 hypervisor is installed directly on the physical server hardware (bare-metal) beneath any guest operating systems. A Type 2 hypervisor runs as an application on top of an existing host operating system. Type 1 hypervisors offer a performance advantage because they have direct access to hardware without the overhead of an intermediate host operating system, making them more secure, robust, and efficient for enterprise server virtualization.

Marking scheme

1 mark: Type 1 hypervisor runs directly on physical hardware (bare-metal). 1 mark: Type 2 hypervisor runs on top of a host operating system. 1 mark: Advantage of Type 1 is better performance/efficiency due to absence of host OS overhead. 1 mark: Type 1 has greater security/isolation because the host OS cannot be compromised to affect the hypervisor.
Question 8 · Architecture Explanations & Protocols
4 marks
Processors are often categorized as RISC or CISC architectures. Compare how these two architectures differ in terms of their instruction format length and the complexity of their instruction sets.
Show answer & marking scheme

Worked solution

RISC (Reduced Instruction Set Computer) utilizes simple instructions that are of fixed length (typically 32-bit), making them easy to decode and ideal for pipelining. CISC (Complex Instruction Set Computer) utilizes complex, variable-length instructions that can perform multi-step operations (like combining load, calculate, and store in one instruction). While RISC instructions mostly execute in a single clock cycle and rely heavily on registers, CISC instructions can take multiple clock cycles and access memory directly, resulting in a denser program code with fewer instructions but a more complex hardware decoder.

Marking scheme

1 mark: RISC instructions are of fixed length; CISC instructions are of variable length. 1 mark: RISC instructions are simple/perform one basic task; CISC instructions are complex/can perform multiple actions (e.g., load and calculate). 1 mark: RISC instructions typically execute in a single clock cycle; CISC instructions take multiple clock cycles. 1 mark: RISC relies heavily on registers (load/store architecture); CISC allows direct operations on memory.
Question 9 · Architecture Explanations & Protocols
4 marks
The TCP/IP protocol stack manages internet communications. Describe the function of the Transport Layer in this stack, and explain how the Transmission Control Protocol (TCP) ensures the reliable transfer of data.
Show answer & marking scheme

Worked solution

The Transport Layer is responsible for establishing a host-to-host connection, segmenting data, and managing flow control and error checking. TCP achieves reliability by first performing a three-way handshake to establish a connection. During transmission, it assigns sequence numbers to each segment so the receiver can reorder them and detect missing data. The receiver sends acknowledgments (ACKs) for received segments. If the sender does not receive an ACK within a timeout period, it retransmits the missing segment, ensuring error-free delivery.

Marking scheme

1 mark: Function of Transport Layer (establishing host-to-host session / packet segmentation / port addressing). 1 mark: TCP connection establishment (three-way handshake). 1 mark: Packet ordering using sequence numbers. 1 mark: Reliability through acknowledgments (ACKs) and retransmission of lost packets.
Question 10 · Architecture Explanations & Protocols
4 marks
A private local area network (LAN) uses Network Address Translation (NAT) to communicate with external hosts on the public Internet. Explain the role of the NAT translation table in processing incoming and outgoing packets.
Show answer & marking scheme

Worked solution

NAT allows a router to present a single public IP address to the WAN on behalf of multiple devices on a private LAN. When an internal device sends a packet, the router replaces the private source IP address and port with its own public IP address and a unique port number, creating an entry in the NAT translation table. When an incoming response arrives from the Internet, the router inspects the destination port, matches it against the NAT translation table to identify the original private IP address and port, and forwards the packet to the correct internal device.

Marking scheme

1 mark: Purpose of NAT (conserve public IP addresses / hide private IPs). 1 mark: Outgoing translation (replaces private source IP and port with public IP and a unique port). 1 mark: NAT table entry creation (maps internal IP/port to external IP/port). 1 mark: Incoming translation (matches destination port of incoming packet to table to forward to correct internal device).
Question 11 · Architecture Explanations & Protocols
4 marks
Flynn's taxonomy classifies computer architectures based on instruction and data streams. Define the term MIMD (Multiple Instruction Multiple Data) and explain why it is suited for parallel processing compared to SISD (Single Instruction Single Data).
Show answer & marking scheme

Worked solution

MIMD (Multiple Instruction Multiple Data) refers to an architecture where multiple processing cores or processors execute different instructions on different datasets at the same time. This is standard in modern multi-core computers. In contrast, SISD (Single Instruction Single Data) features a single processor that executes a single instruction stream on one data stream at a time (sequential execution). MIMD is highly suited for parallel processing because different tasks (or parts of a single task) can be divided and processed concurrently across different cores, greatly increasing computing speed and throughput.

Marking scheme

1 mark: Definition of MIMD (multiple processors/cores executing different instructions on different data streams concurrently). 1 mark: Definition of SISD (single instruction executed sequentially on a single data stream at a time). 1 mark: Contrast in execution (MIMD allows parallel execution of independent tasks; SISD is strictly sequential). 1 mark: Performance benefit (MIMD handles multi-threaded applications and complex simulations much faster by dividing the computational load).
Question 12 · written
4 marks
An algorithm evaluates the Reverse Polish Notation (RPN) expression: \(12 \quad 4 \quad / \quad 5 \quad * \quad 3 \quad 2 \quad \wedge \quad -\). Assume a stack is used to evaluate this expression, and the stack grows from left to right (where the rightmost element is the top of the stack). State the contents of the stack immediately after each of the following operators has been processed:

1. The division operator (/)
2. The multiplication operator (*)
3. The exponentiation operator (\(\wedge\))
4. The subtraction operator (-)
Show answer & marking scheme

Worked solution

Step-by-step evaluation using a stack:
- Push 12: [12]
- Push 4: [12, 4]
- Process '/': Pop 4, Pop 12. Evaluate 12 / 4 = 3. Push 3. Stack becomes [3].
- Push 5: [3, 5]
- Process '*': Pop 5, Pop 3. Evaluate 3 * 5 = 15. Push 15. Stack becomes [15].
- Push 3: [15, 3]
- Push 2: [15, 3, 2]
- Process '^': Pop 2, Pop 3. Evaluate 3^2 = 9. Push 9. Stack becomes [15, 9].
- Process '-': Pop 9, Pop 15. Evaluate 15 - 9 = 6. Push 6. Stack becomes [6].

Marking scheme

Award 1 mark for each correct stack state after the respective operator is processed:
- After '/': [3] (or 3)
- After '*': [15] (or 15)
- After '^': [15, 9] (or 15, 9)
- After '-': [6] (or 6)
Accept alternative notation (e.g., without brackets) as long as the elements and their sequence are correct.
Question 13 · written
4 marks
A weighted, undirected graph has five vertices: A, B, C, D, and E. The connections and weights (distances) between the vertices are given below:
- Vertex A is connected to: B (weight 4), C (weight 2)
- Vertex B is connected to: A (weight 4), C (weight 1), D (weight 5)
- Vertex C is connected to: A (weight 2), B (weight 1), D (weight 8), E (weight 10)
- Vertex D is connected to: B (weight 5), C (weight 8), E (weight 2)
- Vertex E is connected to: C (weight 10), D (weight 2)

Using Dijkstra's algorithm starting at vertex A, determine the shortest distance from vertex A to each of the other vertices: B, C, D, and E. State the final shortest distance value for each.
Show answer & marking scheme

Worked solution

We perform Dijkstra's algorithm step-by-step starting from A:
1. Initialize distances: A = 0, B = infinity, C = infinity, D = infinity, E = infinity.
2. Visit A (dist 0). Update neighbors of A: B = 4, C = 2. Visited set = {A}.
3. Next nearest unvisited vertex is C (dist 2). Visit C. Update neighbors of C:
- B can be reached via A->C->B with distance 2 + 1 = 3. Since 3 < 4, update B = 3.
- D can be reached via A->C->D with distance 2 + 8 = 10.
- E can be reached via A->C->E with distance 2 + 10 = 12.
Visited set = {A, C}.
4. Next nearest unvisited vertex is B (dist 3). Visit B. Update neighbors of B:
- D can be reached via A->C->B->D with distance 3 + 5 = 8. Since 8 < 10, update D = 8.
Visited set = {A, C, B}.
5. Next nearest unvisited vertex is D (dist 8). Visit D. Update neighbors of D:
- E can be reached via A->C->B->D->E with distance 8 + 2 = 10. Since 10 < 12, update E = 10.
Visited set = {A, C, B, D}.
6. Visit E (dist 10). Visited set = {A, C, B, D, E}.

Final shortest distances: B = 3, C = 2, D = 8, E = 10.

Marking scheme

Award 1 mark for each correct final shortest distance:
- Distance to B: 3 (1 mark)
- Distance to C: 2 (1 mark)
- Distance to D: 8 (1 mark)
- Distance to E: 10 (1 mark)
Question 14 · written
4 marks
Convert the following infix expression into Reverse Polish Notation (RPN):

\(((X + Y) * Z) - (W / (U + V))\)

Show your working by writing down:
1. The RPN representation of the sub-expression: \((X + Y) * Z\)
2. The RPN representation of the sub-expression: \(W / (U + V)\)
3. The final RPN representation of the entire expression.
Show answer & marking scheme

Worked solution

Step-by-step conversion:
1. Convert the sub-expression \((X + Y) * Z\):
- Convert parenthesis: \(X + Y\) becomes \(X Y +\)
- Multiply by Z: \(X Y + Z *\)

2. Convert the sub-expression \(W / (U + V)\):
- Convert parenthesis: \(U + V\) becomes \(U V +\)
- Divide W by the result: \(W U V + /\)

3. Convert the entire expression \(((X + Y) * Z) - (W / (U + V))\):
- Join the two converted halves using the subtraction operator: \([Part 1] [Part 2] -\)
- This yields: \(X Y + Z * W U V + / -\)

Marking scheme

- Award 1 mark for correct RPN of \((X + Y) * Z\): `X Y + Z *`
- Award 1 mark for correct RPN of \(W / (U + V)\): `W U V + /`
- Award 2 marks for correct final RPN: `X Y + Z * W U V + / -` (Award 1 mark if there is only one minor error in the final combination, such as an incorrect final operator or incorrect order of operands).
Question 15 · Syllabus Stack Declarations / Initialisations
3 marks
An Abstract Data Type (ADT) Stack is to be implemented procedurally using a 1D array.

Write pseudocode declarations and initialisation statements to:
1. Declare a global 1D array named `StackArray` to store up to 50 integer elements (with index 0 to 49).
2. Declare a global pointer variable `TopPointer` to keep track of the top of the stack.
3. Initialise `TopPointer` to represent an empty stack.
Show answer & marking scheme

Worked solution

To implement a stack procedurally, we declare the array and the pointer as global variables:

```pseudocode
DECLARE StackArray : ARRAY[0:49] OF INTEGER
DECLARE TopPointer : INTEGER

TopPointer <- -1
```

Setting `TopPointer` to `-1` indicates that there are currently no elements in the stack, as the array is 0-indexed.

Marking scheme

1 mark: Correct declaration of 1D array `StackArray` of size 50 (indices 0 to 49) of type `INTEGER`.
1 mark: Correct declaration of `TopPointer` as `INTEGER`.
1 mark: Initialisation of `TopPointer` to `-1` (Accept: `0` if candidate specifies 1-indexed array, but array index in question was explicitly 0 to 49).
Question 16 · Syllabus Stack Declarations / Initialisations
3 marks
A programmer is implementing a Stack data structure as an object-oriented class named `BookStack`.

Write pseudocode to define the class `BookStack`. The definition must include:
- Private attribute `TitleArray`: an array of 20 strings (indices 0 to 19).
- Private attribute `Top`: an integer pointer to the top of the stack.
- A public constructor method `NEW()` which initialises `Top` to represent an empty stack.

You only need to write the class header, attribute declarations, and the constructor method.
Show answer & marking scheme

Worked solution

The class definition containing the required private attributes and the constructor initialising the top pointer is as follows:

```pseudocode
CLASS BookStack
PRIVATE TitleArray : ARRAY[0:19] OF STRING
PRIVATE Top : INTEGER

PUBLIC PROCEDURE NEW()
Top <- -1
ENDPROCEDURE
ENDCLASS
```

Marking scheme

1 mark: Correct class header, footer, and attribute declarations with `PRIVATE` keyword (both `TitleArray` as an array of 20 strings and `Top` as an integer).
1 mark: Correct constructor method header (`PUBLIC PROCEDURE NEW()`) and closing statement.
1 mark: Correct initialisation `Top <- -1` inside the constructor.
Question 17 · Syllabus Stack Declarations / Initialisations
3 marks
A stack is represented by a global 1D array `NamesStack` of size 100 (indices 0 to 99) of type `STRING`, and a global pointer `TopPtr` of type `INTEGER`.

Write a pseudocode procedure `InitializeStack()` that prepares this stack for use by:
- Setting all elements of `NamesStack` to the empty string `""`.
- Setting `TopPtr` to indicate that the stack is empty.
Show answer & marking scheme

Worked solution

The procedure needs to loop through all valid indices of the array (from 0 to 99) and assign an empty string to each slot. After the loop, the top pointer is set to -1:

```pseudocode
PROCEDURE InitializeStack()
FOR Index <- 0 TO 99
NamesStack[Index] <- ""
ENDFOR
TopPtr <- -1
ENDPROCEDURE
```

Marking scheme

1 mark: Correct procedure header, footer, and a loop that correctly iterates 100 times (from 0 to 99).
1 mark: Assigning `""` to `NamesStack[Index]` (or equivalent loop variable) inside the loop.
1 mark: Assigning `-1` to `TopPtr` outside the loop.

Paper 4 Practical

Write programs in Java, Python or VB. Save work in an evidence document with screenshots.
16 Question · 56.89999999999999 marks
Question 1 · OOP Class Structure / Inheritance Declaring
3 marks
An object-oriented program is being designed to manage musical instruments. Write Python code to define a class named Instrument. The class must meet the following requirements:
- It has two private attributes: __name (string) and __category (string).
- It has a constructor (__init__) that accepts name and category as parameters and assigns them to the private attributes.
Show answer & marking scheme

Worked solution

The following Python code declares the class with its private attributes and constructor:

```python
class Instrument:
def __init__(self, name, category):
self.__name = name
self.__category = category
```

Marking scheme

1 Mark: Correct class header definition (class Instrument:)
1 Mark: Correct constructor header with parameters (def __init__(self, name, category):)
1 Mark: Correct assignment of parameters to private attributes with double underscores (__name and __category).
Question 2 · OOP Class Structure / Inheritance Declaring
3 marks
A subclass named StringInstrument needs to inherit from the Instrument class. Write Python code to define this subclass. The class must meet the following requirements:
- It inherits from the Instrument class.
- It has an additional private attribute: __numberOfStrings (integer).
- It has a constructor that accepts name, category, and numberOfStrings as parameters, calls the superclass constructor with the appropriate arguments, and initializes the new attribute.
Show answer & marking scheme

Worked solution

The subclass StringInstrument inherits from Instrument and invokes its parent constructor using super():

```python
class StringInstrument(Instrument):
def __init__(self, name, category, numberOfStrings):
super().__init__(name, category)
self.__numberOfStrings = numberOfStrings
```

Marking scheme

1 Mark: Correct subclass header demonstrating inheritance (class StringInstrument(Instrument):)
1 Mark: Calling the superclass constructor correctly (super().__init__(name, category))
1 Mark: Declaring and initializing the private attribute __numberOfStrings.
Question 3 · OOP Class Structure / Inheritance Declaring
3 marks
Write Java code to define a class named Product. The class must meet the following requirements:
- It has two private fields: productID (String) and price (double).
- It has a constructor that initializes these fields from parameters.
- It has public getter methods for both fields.
Show answer & marking scheme

Worked solution

The complete Java class definition with private fields, constructor, and getter methods:

```java
public class Product {
private String productID;
private double price;

public Product(String productID, double price) {
this.productID = productID;
this.price = price;
}

public String getProductID() {
return this.productID;
}

public double getPrice() {
return this.price;
}
}
```

Marking scheme

1 Mark: Correctly declaring private fields with correct data types (String and double).
1 Mark: Correctly defining the constructor initializing both fields.
1 Mark: Defining public getter methods returning the correct properties.
Question 4 · OOP Class Structure / Inheritance Declaring
3 marks
Write Java code to define a subclass named DiscountedProduct that inherits from the Product class. The subclass must meet the following requirements:
- It inherits from Product.
- It has an additional private field: discountRate (double).
- It has a constructor that accepts productID, price, and discountRate as parameters, calls the superclass constructor to initialize inherited fields, and initializes discountRate.
Show answer & marking scheme

Worked solution

The Java subclass utilizes the `extends` keyword and calls the parent constructor via `super()`:

```java
public class DiscountedProduct extends Product {
private double discountRate;

public DiscountedProduct(String productID, double price, double discountRate) {
super(productID, price);
this.discountRate = discountRate;
}
}
```

Marking scheme

1 Mark: Class declaration with inheritance (extends Product).
1 Mark: Correct declaration of private field discountRate (double).
1 Mark: Constructor calling super(productID, price) and initializing discountRate.
Question 5 · OOP Class Structure / Inheritance Declaring
3 marks
Write Python code to define an abstract class named Shape. The class must meet the following requirements:
- It imports and uses appropriate elements from the abc module.
- It has a constructor that initializes a private attribute __color (string).
- It declares an abstract method named getArea that accepts no arguments (except self).
Show answer & marking scheme

Worked solution

The abstract class Shape utilizes the abc module to declare an abstract class and abstract method:

```python
from abc import ABC, abstractmethod

class Shape(ABC):
def __init__(self, color):
self.__color = color

@abstractmethod
def getArea(self):
pass
```

Marking scheme

1 Mark: Correct import statement and class definition inheriting from ABC.
1 Mark: Correct constructor initializing private attribute __color.
1 Mark: Correct declaration of abstract method getArea using the @abstractmethod decorator.
Question 6 · practical
4 marks
A circular queue is implemented using a global 1-dimensional array `QueueArray` of 10 integers. The queue is managed by three global variables: `HeadPointer` (index of the front element, initially 0), `TailPointer` (index of the last inserted element, initially 0), and `NumItems` (the total number of items currently in the queue, initially 0). Write a Python function `enqueue(Item)` that takes an integer `Item` as a parameter. The function must check if the queue is full. If full, it must return `False`. If not full, it must insert the item at the position pointed to by `TailPointer`, update the circular `TailPointer`, increment `NumItems`, and return `True`.
Show answer & marking scheme

Worked solution

```python
QueueArray = [0] * 10
HeadPointer = 0
TailPointer = 0
NumItems = 0

def enqueue(Item):
global TailPointer, NumItems, QueueArray
if NumItems == 10:
return False
QueueArray[TailPointer] = Item
TailPointer = (TailPointer + 1) % 10
NumItems += 1
return True
```

Marking scheme

1 Mark: Checking if queue is full using `NumItems == 10`.
1 Mark: Inserting `Item` at the index indicated by `TailPointer`.
1 Mark: Correct circular pointer update using `(TailPointer + 1) % 10` (or manual conditional check).
1 Mark: Correctly incrementing `NumItems` and returning `True`/`False` appropriately.
Question 7 · practical
4 marks
A linear queue is implemented using a 1-dimensional array `QueueData` of 8 string elements. Two global integer variables, `Head` and `Tail`, are initialized to 0. `Head` points to the front of the queue, and `Tail` points to the next available index for insertion. Write a Python function `dequeue()` that checks if the queue is empty. If the queue is empty, the function returns the string "EMPTY". Otherwise, the function retrieves the item at the `Head` pointer, increments `Head` by 1, and returns the retrieved item.
Show answer & marking scheme

Worked solution

```python
QueueData = [""] * 8
Head = 0
Tail = 0

def dequeue():
global Head, QueueData
if Head == Tail:
return "EMPTY"
item = QueueData[Head]
Head += 1
return item
```

Marking scheme

1 Mark: Correctly checks if the queue is empty using `Head == Tail`.
1 Mark: Correctly retrieves the element from `QueueData[Head]`.
1 Mark: Correctly increments `Head` by 1.
1 Mark: Correctly returns either "EMPTY" or the retrieved item.
Question 8 · practical
4 marks
A queue is implemented using a 1-dimensional array `DataQueue` of 5 string elements. The front of the queue is always maintained at index 0. A global integer `TailPointer` tracks the next empty index (initially 0). Write a Python function `dequeue_shift()` that removes the item at index 0. If the queue is empty (i.e., `TailPointer` is 0), the function must return `None`. Otherwise, it must store the item at index 0, shift all subsequent elements one space to the left, decrement `TailPointer` by 1, and return the stored item.
Show answer & marking scheme

Worked solution

```python
DataQueue = [""] * 5
TailPointer = 0

def dequeue_shift():
global TailPointer, DataQueue
if TailPointer == 0:
return None
item = DataQueue[0]
for i in range(1, TailPointer):
DataQueue[i - 1] = DataQueue[i]
TailPointer -= 1
return item
```

Marking scheme

1 Mark: Checking if the queue is empty using `TailPointer == 0` and returning `None`.
1 Mark: Storing the value of the element at index 0 before updating.
1 Mark: Using a loop to shift subsequent active elements (`range(1, TailPointer)`) one space left.
1 Mark: Decrementing `TailPointer` and returning the stored item.
Question 9 · practical
4 marks
A priority queue is implemented using a 1-dimensional array of record objects named `QueueArray` of size 5. Each object has attributes `Data` (string) and `Priority` (integer, where 1 is the highest priority and 5 is the lowest). The array is kept sorted in ascending order of priority (highest priority at index 0). Assuming a global integer `NumItems` tracks the number of elements, write a Python function `insert_priority(NewData, NewPriority)` that inserts a new item into its correct sorted position in the queue. You may assume the queue is not full.
Show answer & marking scheme

Worked solution

```python
class Element:
def __init__(self, data, priority):
self.Data = data
self.Priority = priority

QueueArray = [None] * 5
NumItems = 0

def insert_priority(NewData, NewPriority):
global NumItems, QueueArray
new_item = Element(NewData, NewPriority)
i = NumItems - 1
while i >= 0 and QueueArray[i].Priority > NewPriority:
QueueArray[i + 1] = QueueArray[i]
i -= 1
QueueArray[i + 1] = new_item
NumItems += 1
```

Marking scheme

1 Mark: Declaring and initializing a new record object/element with `NewData` and `NewPriority`.
1 Mark: Writing an insertion shift loop that moves elements with lower priority (higher numeric priority value) one index right.
1 Mark: Inserting the new item at the correct insertion index (`i + 1`).
1 Mark: Correctly incrementing `NumItems` by 1.
Question 10 · Recursive iteration counting code block
3.3 marks
An algorithm is required to calculate the number of unique paths from the origin (0, 0) to a grid point (X, Y) moving only up or right. This is implemented using a recursive function CountPaths(X, Y). To analyze the efficiency, the programmer wants to count the total number of times the recursive function is called. Write program code in Python, Java, or Visual Basic to: 1. Declare a global integer variable CallCount and initialize it to 0. 2. Write the recursive function CountPaths(X, Y) which: - Increments CallCount by 1 on every entry. - Returns 1 if X is 0 or Y is 0 (base case). - Otherwise, returns CountPaths(X - 1, Y) + CountPaths(X, Y - 1). 3. In the main program, call CountPaths(3, 2), then output the returned result and the value of CallCount. Save your program and take a screenshot of the execution output as evidence.
Show answer & marking scheme

Worked solution

Python solution:

CallCount = 0

def CountPaths(X, Y):
global CallCount
CallCount += 1
if X == 0 or Y == 0:
return 1
return CountPaths(X - 1, Y) + CountPaths(X, Y - 1)

result = CountPaths(3, 2)
print("Returned value:", result)
print("CallCount:", CallCount)

Marking scheme

1 mark: Correct base cases (returning 1 when X == 0 or Y == 0).
1 mark: Correct recursive step summing the two calls with decremented X and Y.
1 mark: Correctly updating and displaying the global CallCount variable resulting in 19.
Question 11 · Recursive iteration counting code block
3.3 marks
The Collatz sequence is generated recursively starting from an integer N. A recursive function CollatzCount(N) counts the number of steps to reach 1. Write program code in Python, Java, or Visual Basic to: 1. Declare a global integer variable CallCount and initialize it to 0. 2. Write the recursive function CollatzCount(N) which: - Increments CallCount by 1 on every entry. - Returns 0 if N is 1. - Returns 1 + CollatzCount(N // 2) if N is even. - Returns 1 + CollatzCount(3 * N + 1) if N is odd. 3. In the main program, call CollatzCount(6), then output the returned step count and the value of CallCount. Save your program and take a screenshot of the execution output as evidence.
Show answer & marking scheme

Worked solution

Python solution:

CallCount = 0

def CollatzCount(N):
global CallCount
CallCount += 1
if N == 1:
return 0
elif N % 2 == 0:
return 1 + CollatzCount(N // 2)
else:
return 1 + CollatzCount(3 * N + 1)

steps = CollatzCount(6)
print("Returned step count:", steps)
print("CallCount:", CallCount)

Marking scheme

1 mark: Correct base case (returning 0 if N == 1).
1 mark: Correct recursive cases for even and odd conditions with step additions.
1 mark: Correctly updating and printing global CallCount resulting in 9.
Question 12 · Recursive iteration counting code block
3.3 marks
A recursive binary search algorithm searches a sorted 1D array of integers. A programmer wants to track the exact number of recursive calls made during a search. Write program code in Python, Java, or Visual Basic to: 1. Declare a global integer variable CallCount and initialize it to 0. 2. Write a recursive function BinarySearchCount(Arr, Low, High, Target) which: - Increments CallCount by 1 on every entry. - Returns -1 if Low > High. - Calculates Mid as integer division of (Low + High) / 2. - Returns Mid if Arr[Mid] == Target. - Recursively searches the left half if Target < Arr[Mid]. - Recursively searches the right half if Target > Arr[Mid]. 3. In the main program, define Arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]. 4. Call BinarySearchCount(Arr, 0, 9, 10) and output the return value and the value of CallCount. Save your program and take a screenshot of the execution output as evidence.
Show answer & marking scheme

Worked solution

Python solution:

CallCount = 0

def BinarySearchCount(Arr, Low, High, Target):
global CallCount
CallCount += 1
if Low > High:
return -1
Mid = (Low + High) // 2
if Arr[Mid] == Target:
return Mid
elif Target < Arr[Mid]:
return BinarySearchCount(Arr, Low, Mid - 1, Target)
else:
return BinarySearchCount(Arr, Mid + 1, High, Target)

Arr = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
result = BinarySearchCount(Arr, 0, 9, 10)
print("Returned value:", result)
print("CallCount:", CallCount)

Marking scheme

1 mark: Correct base cases (Low > High returning -1, and Target found returning Mid).
1 mark: Correct mid calculation and recursive calls with adjusted boundaries.
1 mark: Correctly counting recursive calls (CallCount = 5) and displaying the expected results.
Question 13 · practical
4 marks
An application stores custom configuration data in a single string format where key-value pairs are separated by semicolons, and keys and values are separated by colons (e.g., "timeout:30;retries:3;port:8080;").

Write a program function/method `GetValue(ConfigString : String, TargetKey : String) -> String` in Python, Java, or VB.NET that searches for `TargetKey` in `ConfigString` and returns its associated value.

**To ensure compatibility and performance under specific system constraints, you must NOT use any built-in split functions (such as `.split()`) or regular expressions.** Instead, parse the string character by character to extract the keys and values.

Save your work in your evidence document. Include a test run showing the function correctly returning '5000' when called with `GetValue("host:localhost;port:5000;db:users;", "port")`.
Show answer & marking scheme

Worked solution

The function traverses the input `ConfigString` character by character. It maintains a boolean flag `is_value` to determine if it is currently reading a key (before the colon) or a value (after the colon). When a semicolon is encountered, it checks if the built-up `current_key` matches the target. If yes, it returns the accumulated `current_value`. If not, both key and value buffers are reset. This allows key-value extraction without utilizing `.split()` or other banned libraries.

Example Test Execution:
`print(GetValue("host:localhost;port:5000;db:users;", "port"))` prints `5000`.

Marking scheme

Marks are awarded as follows:
- 1 Mark: Iteration structure that correctly processes every character of the string in order.
- 1 Mark: Tracking state using a flag or variable to distinguish between keys and values (based on `:` identifier).
- 1 Mark: Identifying the end of a key-value pair (based on `;` identifier) and performing comparison against `TargetKey`.
- 1 Mark: Correctly returning the associated value string on match, and returning empty string on mismatch.
Question 14 · practical
4 marks
A system reads a custom CSV record where elements are separated by commas. However, if a field is enclosed in single quotes ('), any comma inside those single quotes must be treated as normal character data and not as a field separator.

Write a function `ExtractField(Record : String, TargetIndex : Integer) -> String` in Python, Java, or VB.NET that parses the string character by character and returns the field at `TargetIndex` (0-indexed), with the surrounding single quotes removed from the final returned string. If the target index does not exist in the record, return an empty string.

**Do not use any built-in split functions or regular expressions.**

Save your work in your evidence document. Include a test run showing the function output when called with `ExtractField("apple,'banana,grape',cherry", 1)`.
Show answer & marking scheme

Worked solution

The algorithm implements a state-machine parser. It tracks whether the scanner is currently inside a quote block using a boolean flag `in_quotes`. Commas only trigger field splitting when `in_quotes` is false. Quotation marks are omitted from the buffer, solving the requirement to clean quotes from the returned string.

Example Test Execution:
`print(ExtractField("apple,'banana,grape',cherry", 1))` prints `banana,grape`.

Marking scheme

Marks are awarded as follows:
- 1 Mark: Character traversal loop with toggle state flag `in_quotes` activated upon matching the quote character.
- 1 Mark: Distinguishing between a separating comma (outside quotes) and literal commas (within quotes).
- 1 Mark: Tracking and incrementing the field index counter, and resetting the field buffer appropriately.
- 1 Mark: Correctly extracting and returning the requested field (handling end-of-string fields) and omitting quotes from the final output.
Question 15 · practical
4 marks
A compression algorithm encodes text using a simplified run-length encoding (RLE) scheme. For example, 'A3B12C4' represents three 'A's, twelve 'B's, and four 'C's.

Write a function `DecompressString(Compressed : String) -> String` in Python, Java, or VB.NET that decodes this format. The function must traverse the compressed string character by character, extract each letter and its corresponding multi-digit frequency, and construct the full decompressed string.

**Do not use any built-in split functions or regular expressions.**

Save your work in your evidence document. Include a test run showing the function output when called with `DecompressString("X5Y11Z2")`.
Show answer & marking scheme

Worked solution

The algorithm parses the compressed string sequentially. When an alphabetic character is encountered, it signifies the end of the previous run (if there was one). The run is decompressed by multiplying the character by the accumulated count (converted to an integer) and appending it to `result`. The code then sets `current_char` to the new letter and resets the count buffer. Digits are continuously appended to the `current_count` buffer to accommodate multi-digit repetitions. A final decompression cycle must execute after the loop concludes to process the last run.

Example Test Execution:
`print(DecompressString("X5Y11Z2"))` prints `XXXXXYYYYYYYYYYYZZ`.

Marking scheme

Marks are awarded as follows:
- 1 Mark: Logic to distinguish alphabetical characters (new runs) from digit characters (run counts).
- 1 Mark: Appending the correct repetition of characters to the result string when a new run begins.
- 1 Mark: Accumulating multi-digit counts as strings before parsing to integer to support numbers > 9.
- 1 Mark: Replicating the decompression step after the loop completes to handle the final sequence.
Question 16 · practical
4 marks
A markup engine parses a simplified document where tags are formatted as `[tag]content[/tag]`.

Write a function `ExtractTagContent(Markup : String, Tag : String) -> String` in Python, Java, or VB.NET that searches for the tags `[Tag]` and `[/Tag]` within the string `Markup` and returns the `content` enclosed inside. If either the opening or closing tag is missing or misplaced, return an empty string.

**Do not use any built-in split, index, find, or search functions, nor regular expressions.** You must parse the string character by character to find the tags.

Save your work in your evidence document. Include a test run showing the function output when called with `ExtractTagContent("[bold]Welcome to CIE[/bold]", "bold")`.
Show answer & marking scheme

Worked solution

The function dynamically creates the target string bounds `[Tag]` and `[/Tag]`. It scans the string without relying on built-in find/search methods by defining a helper comparison mechanism. It identifies the index directly following the open tag and the index directly preceding the close tag, checking for valid placement. Finally, it constructs the resulting substring character-by-character from between those indexes.

Example Test Execution:
`print(ExtractTagContent("[bold]Welcome to CIE[/bold]", "bold"))` prints `Welcome to CIE`.

Marking scheme

Marks are awarded as follows:
- 1 Mark: Correctly dynamic building of the open and close tags from the `Tag` argument.
- 1 Mark: Parsing character-by-character with loop structure to find the open tag position without built-in index/find routines.
- 1 Mark: Correctly identifying the close tag position relative to the open tag.
- 1 Mark: Reconstructing and returning the inner text, validating tag positions (returning empty string if tags are missing or out of order).

Wondering how well you actually know this?

Thinka is an AI practice app for DSE students — unlimited questions, instant auto-marking, and detailed step-by-step solutions. 100,000+ students use it to confirm they actually know it, not just think they do.

Want more questions like this? Practice unlimited on Thinka — instant answers included.

Start Practising Free