An original Thinka practice paper modelled on the structure and difficulty of the Nov 2024 (V2) Cambridge International A Level Computer Science (9618) paper. Not affiliated with or reproduced from Cambridge.
Paper 12: Theory Fundamentals
Answer all questions. Calculators must not be used.
9 PastPaper.question · 74.97 PastPaper.marks
PastPaper.question 1 · Short Answer
8.33 PastPaper.marks
A sound recording has the following characteristics: - Sampling rate: 44,100 Hz - Sampling resolution: 16 bits - Number of channels: 2 (stereo) - Duration: 10 seconds
(a) State the formula used to calculate the size of an uncompressed sound file. (b) Calculate the storage size of this file in Megabytes (MB) (using base 10 where 1 MB = 1,000,000 bytes) and Mebibytes (MiB) (using base 2 where 1 MiB = 1,048,576 bytes). Show your working.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) The standard formula to calculate the size of an uncompressed sound file in bits is: \text{File Size (bits)} = \text{Sampling Rate (Hz)} \times \text{Sampling Resolution (bits)} \times \text{Number of Channels} \times \text{Duration (seconds)}
Part (a): [2 marks] - 1 mark for identifying the product of sampling rate, resolution, and duration. - 1 mark for including the number of channels.
Part (b): [6 marks] - 1 mark for showing correct total bits calculation: \(44,100 \times 16 \times 2 \times 10 = 14,112,000\text{ bits}\). - 1 mark for dividing by 8 to get bytes: \(1,764,000\text{ bytes}\). - 1 mark for dividing bytes by 1,000,000 for decimal representation. - 1 mark for correct decimal answer (1.76 MB, accept 1.764 MB). - 1 mark for dividing bytes by 1,048,576 (or 1024 * 1024) for binary representation. - 1 mark for correct binary answer (1.68 MiB, accept 1.682 MiB).
PastPaper.question 2 · Short Answer
8.33 PastPaper.marks
A computer connected to a local network has the IPv4 address 192.168.42.75 and a subnet mask of 255.255.255.224.
Explain how the computer determines whether the destination IP address 192.168.42.110 is on the same local network or on a different network. Show the relevant binary calculations.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
1. Convert the final octets of the subnet mask, local IP, and destination IP to binary: - Subnet Mask (224): 11100000 - Local IP (75): 01001011 - Destination IP (110): 01101110
2. Perform bitwise AND between Local IP and Subnet Mask: - 01001011 AND 11100000 = 01000000 (which is 64 in denary). - Therefore, the local network ID is 192.168.42.64.
3. Perform bitwise AND between Destination IP and Subnet Mask: - 01101110 AND 11100000 = 01100000 (which is 96 in denary). - Therefore, the destination network ID is 192.168.42.96.
4. Compare the two network IDs: - Since 192.168.42.64 does not equal 192.168.42.96, the destination address is on a different (remote) network, meaning the packet must be sent to the default gateway (router).
PastPaper.markingScheme
- 1 mark for stating that a bitwise AND operation is performed on the IP address and the subnet mask. - 1 mark for converting the mask octet 224 to binary: 11100000. - 1 mark for converting local IP octet 75 to binary: 01001011. - 1 mark for converting destination IP octet 110 to binary: 01101110. - 1 mark for calculating correct local network ID octet: 64 (01000000). - 1 mark for calculating correct destination network ID octet: 96 (01100000). - 1 mark for stating that both network IDs are compared. - 1 mark for concluding that since they differ, the destination is on a remote network (default gateway used).
PastPaper.question 3 · Short Answer
8.33 PastPaper.marks
An automated system regulates the climate inside a commercial greenhouse. The system is designed to keep the temperature strictly between 18 degrees Celsius and 25 degrees Celsius.
Describe how sensors, a microprocessor, and actuators work together to maintain the temperature within this range.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
The system operates as a closed-loop control system: 1. A temperature sensor continuously measures the ambient temperature inside the greenhouse and outputs an analog signal. 2. This analog signal is converted to digital values by an Analog-to-Digital Converter (ADC) so the microprocessor can process it. 3. The microprocessor receives the digital values and compares them against the stored threshold limits (18°C and 25°C). 4. If the measured temperature is below 18°C, the microprocessor sends a control signal to the actuator for the heating element to turn it on. 5. If the temperature is above 25°C, the microprocessor sends a control signal to the actuator for the ventilation fan or window opener to cool the greenhouse. 6. If the temperature is within the range, the microprocessor sends signals to turn off or keep off both actuators. 7. Digital-to-Analog Converters (DAC) may be used if the actuators require analog inputs. 8. The process repeats continuously in an infinite loop.
PastPaper.markingScheme
- 1 mark: Sensor continuously measures physical temperature. - 1 mark: ADC converts analog sensor signals to digital values. - 1 mark: Microprocessor compares digital input with stored target ranges (18°C and 25°C). - 1 mark: Microprocessor takes decision based on comparison (if low, trigger heater; if high, trigger fan). - 1 mark: Microprocessor sends control signal to actuators. - 1 mark: Actuators perform physical action (e.g. heating or ventilation). - 1 mark: DAC is mentioned as necessary for actuator control (if analog actuators used). - 1 mark: System operates continuously in a feedback/closed loop.
PastPaper.question 4 · Tracing
8.33 PastPaper.marks
An assembly language program is executed with the following initial memory state: - Address 203: 2 - Address 204: 4 - Address 205: 0 - Address 250: 0
The assembly instructions are: ```assembly LDI 0 STO 250 LDD 204 STO 205 Loop: LDD 250 ADD 205 STO 250 LDD 205 DEC ACC STO 205 CMP 203 JPN Loop ``` Trace the execution of this program. State the final values of the Accumulator (ACC), memory address 205, and memory address 250 upon termination.
- 2 marks for tracking the accumulator (ACC) correctly through both iterations. - 2 marks for tracking Memory[205] correctly (decremented from 4 to 3, then to 2). - 2 marks for tracking Memory[250] correctly (accumulating 0 + 4 = 4, then 4 + 3 = 7). - 2 marks for correctly identifying when the loop terminates (when ACC matches address 203 containing 2). - 0.33 marks for finalizing all three values accurately in the written response.
PastPaper.question 5 · Short Answer
8.33 PastPaper.marks
Explain three differences between a compiler and an interpreter. For each difference, describe how it affects the development and execution of program code.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Differences between a Compiler and an Interpreter:
1. Translation Process: - Compiler: Translates the entire source code into machine code/object code in one go before execution. - Interpreter: Translates the source code line-by-line, executing each line immediately after translation. - Development Impact: Interpreters make prototyping/debugging faster as you see immediate results, whereas compilers require a full compilation cycle before testing.
2. Output Product: - Compiler: Generates an independent executable file (.exe or object code) that can run without the source code or compiler present. - Interpreter: Does not produce an executable file; the source code and the interpreter are required on the host system every time the program runs. - Development/Distribution Impact: Compiled software is easier to distribute commercially without exposing source code, while interpreted code requires distributing source files.
3. Speed of Execution: - Compiler: The compiled executable runs very fast since no translation happens at runtime. - Interpreter: Runs slower because every instruction must be translated and then executed dynamically.
4. Error Diagnostics: - Compiler: Reports all syntax errors at the end of compilation, which must all be fixed before an executable is produced. - Interpreter: Stops execution the moment an error is found, allowing the developer to identify the exact line containing the error instantly.
PastPaper.markingScheme
Award up to 8 marks (maximum 3 marks for identifying differences, and 5 marks for explanations of development/execution impacts): - 1 mark per identified difference (up to 3): * Entire file vs Line-by-line translation * Creates executable vs No executable * Execution speed (Fast vs Slow translation-at-runtime) * All errors at end vs Halting on first error - 1 mark for describing development impact of translation method (e.g. interpreter faster for trial-and-error debugging). - 1 mark for describing executable impact (e.g. compiled hides source code; interpreted exposes it/requires target interpreter). - 1 mark for describing speed impact on execution. - 1 mark for describing error diagnostic differences during coding.
PastPaper.question 6 · Short Answer
8.33 PastPaper.marks
A system uses an 8-bit transmission system with even parity.
(a) Identify which of the following received bytes contain transmission errors, and explain your reasoning: - Byte A: 11010110 - Byte B: 10110100
(b) Explain how a checksum is calculated and used to verify data integrity during transmission.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) Even parity requires that the number of '1' bits in a byte is even. - Byte A (11010110) contains five '1' bits. Five is an odd number, so Byte A has a transmission error. - Byte B (10110100) contains four '1' bits. Four is an even number, so no error is detected in Byte B.
(b) How a checksum works: 1. Before transmission, the sender runs an algorithm on the data block to produce a calculated value called the checksum. 2. The checksum is sent along with the data. 3. Upon receiving the data, the receiver runs the same algorithm on the received data blocks to compute its own checksum value. 4. The receiver compares its computed checksum with the received checksum. 5. If they match, the data is assumed error-free. If they do not match, an error is detected, and the receiver requests a retransmission.
PastPaper.markingScheme
Part (a): [3 marks] - 1 mark: Identify Byte A contains an error and Byte B does not. - 1 mark: Explain that Byte A contains five '1' bits, which is odd, violating even parity. - 1 mark: Explain that Byte B contains four '1' bits, which is even, satisfying even parity.
Part (b): [5 marks] - 1 mark: Mention checksum is calculated on blocks of data using an algorithm. - 1 mark: Checksum value is appended to the payload / transmitted with the data. - 1 mark: Receiver recalculates the checksum using the same algorithm. - 1 mark: Receiver compares the calculated value with the received checksum. - 1 mark: If they differ, an error has occurred and retransmission is requested.
PastPaper.question 7 · Short Answer
8.33 PastPaper.marks
(a) Contrast Open Source Software with Commercial (Proprietary) Software in terms of source code availability, modification rights, and costs. (b) Explain the differences between Shareware and Freeware.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) Open Source vs Commercial (Proprietary) Software: - Source Code Availability: Open Source software makes its human-readable source code public. Commercial software distributes only compiled binaries; the source code is kept secret. - Modification Rights: Open Source licenses permit users to inspect, modify, and redistribute their own versions of the code. Commercial software licenses strictly forbid reverse engineering, alteration, or distribution. - Costs: Open Source is usually free of charge. Commercial software requires purchasing a license to use legally.
(b) Shareware vs Freeware: - Shareware is distributed free of charge on a trial basis. It often has limited features, a timed trial period, or regular prompts to pay. To unlock the full system permanently, users must pay. - Freeware is completely free software with no trial period and all features fully functional. However, the software remains proprietary, meaning users are not given the source code and cannot modify it.
PastPaper.markingScheme
Part (a): [5 marks] - 1 mark: Open source provides source code, proprietary/commercial does not (compiled binaries only). - 1 mark: Open source permits modifications and redistribution. - 1 mark: Commercial/proprietary forbids copying, modifications, and redistribution. - 1 mark: Open source is generally free; commercial requires purchasing a license. - 1 mark: Ownership of copyright is retained by the creator in commercial software.
Part (b): [3 marks] - 1 mark: Shareware is distributed on a trial/temporary basis (free initially, requires payment later). - 1 mark: Freeware is distributed permanently free of charge. - 1 mark: Both keep the source code private (unlike open source), but Freeware has no feature/time limitations.
PastPaper.question 8 · Short Answer
8.33 PastPaper.marks
A relational database contains two tables to track library books and loans: - `BOOK(BookID, Title, Author, Genre, PublishedYear)` - `LOAN(LoanID, BookID, MemberID, DateBorrowed, DateReturned)`
Write SQL queries to execute the following requirements: (a) List the `Title` and `Author` of all books where the genre is 'Sci-Fi' and they were published after the year 2015. (b) Insert a new book into the database with `BookID` 'B901', `Title` 'The Digital Age', `Author` 'A. Turing', `Genre` 'Computing', and `PublishedYear` 2023. (c) Update the `DateReturned` of all loans associated with `BookID` 'B104' to the date '2023-10-15'.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) Query to select titles and authors: ```sql SELECT Title, Author FROM BOOK WHERE Genre = 'Sci-Fi' AND PublishedYear > 2015; ```
(b) Query to insert a new book record: ```sql INSERT INTO BOOK (BookID, Title, Author, Genre, PublishedYear) VALUES ('B901', 'The Digital Age', 'A. Turing', 'Computing', 2023); ``` (Note: Column list is optional but recommended. Values must match defined types; strings single-quoted, integer unquoted).
(c) Query to update the loan records: ```sql UPDATE LOAN SET DateReturned = '2023-10-15' WHERE BookID = 'B104'; ```
**(b)** Explain the difference between direct addressing (such as `LDD 150`) and indirect addressing (such as `LDI 152`). Your answer should refer to how the memory is accessed in each case. (3 marks)
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
### Part (a) Trace Table Walkthrough: 1. **(Initial)**: ACC = 0, Memory Address [152] = 0, Memory Address [153] = 0. 2. **LDD 150**: Loads the contents of address 150 directly into the ACC. Address 150 contains 200. ACC becomes **200**. 3. **ADD 151**: Adds the contents of address 151 (which is 4) to the ACC. ACC = 200 + 4 = **204**. 4. **STO 152**: Stores the current ACC value (204) into address 152. Memory Address [152] becomes **204**. 5. **LDI 152**: Indirect load. Look at address 152 (which contains 204), and fetch the value from address 204 (which contains 55). ACC becomes **55**. 6. **INC ACC**: Increments the value in the ACC by 1. ACC = 55 + 1 = **56**. 7. **STO 153**: Stores the current ACC value (56) into address 153. Memory Address [153] becomes **56**. 8. **END**: Stops program execution.
### Part (b) Explanation: - **Direct Addressing**: The address field in the instruction contains the actual memory address where the data is located. Only one memory access cycle is needed to retrieve the operand. - **Indirect Addressing**: The address field contains an address that holds another address (a pointer). This second address is where the actual operand is located. This requires two memory access cycles (one to find the pointer, and a second to retrieve the operand data).
PastPaper.markingScheme
### Part (a) Trace Table (5 Marks Total): - **1 Mark**: ACC correctly updated to `200` after `LDD 150`. - **1 Mark**: ACC correctly updated to `204` after `ADD 151`. - **1 Mark**: Memory Address 152 correctly updated to `204` after `STO 152`. - **1 Mark**: ACC correctly updated to `55` after `LDI 152`. - **1 Mark**: ACC correctly updated to `56` after `INC ACC` AND Memory Address 153 correctly updated to `56` after `STO 153`. *Note: Allow marks if trace table leaves unchanged cells blank or repeats previous values, as long as updates occur on the correct rows.*
### Part (b) Explanation (3 Marks Total): - **1 Mark**: Definition of Direct addressing: the instruction points directly to the memory address of the data. - **1 Mark**: Definition of Indirect addressing: the instruction points to a memory address which contains the address of the data (acts as a pointer). - **1 Mark**: Comparison of memory access: Direct addressing requires one memory access/lookup, whereas indirect addressing requires two memory accesses/lookups.
Paper 22: Problem-solving & Programming
Answer all questions. Refer to the insert for pseudocode functions.
Write a pseudocode function CountActions that takes two parameters: TargetUser (STRING) and TargetAction (STRING). The function must open the text file 'activity.txt' for reading and scan through it.
Each line of the text file 'activity.txt' is of fixed length containing exactly 18 characters, structured as: UserID (6 characters, indices 1-6), a comma (index 7), ActionType (6 characters, indices 8-13), a comma (index 14), and Timestamp (4 characters, indices 15-18). E.g. '100204,UPLOAD,1430'.
The function must count and return the number of times the TargetUser has performed the TargetAction. If the file cannot be opened, or does not exist, the function should return -1.
Assume standard file functions: OPENFILE FOR READ, READFILE , , CLOSEFILE , and EOF().
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
A standard file reading loop is constructed with an EOF check. For each line, the fixed-length layout allows extracting the UserID and ActionType directly using the MID string function. These are compared to the function parameters. A counter tracking matching criteria is incremented and returned. Exception handling (TRY/CATCH) handles potential file open failures gracefully by returning -1.
PastPaper.markingScheme
1 Mark: Correct function header with parameters and return type. 1 Mark: Initialize count to 0. 1 Mark: Try-catch block or equivalent logic to handle file open failure (returns -1). 1 Mark: Correct loop structure using WHILE NOT EOF. 1 Mark: Correct use of READFILE. 2 Marks: Correct string extraction for UserID (indices 1 to 6) and ActionType (indices 8 to 13). 1 Mark: Correct comparison logic for both conditions. 1 Mark: Close file and return count.
A global 2D array StudentGrades of type STRING, sized [1:100, 1:3] contains student grade details. - Column 1: Student ID (e.g., 'STU102') - Column 2: Subject Code (e.g., 'CS9618') - Column 3: Grade (e.g., 'A', 'B', 'C', 'D', 'E', 'U')
Write a pseudocode function FindSubjectCount that takes two parameters: SubjectCode (STRING) and PassGrade (CHAR). The function must search through the array and return the total number of students who achieved the specified PassGrade or a higher grade (e.g. if PassGrade is 'C', then 'A', 'B', and 'C' are acceptable passes, assuming standard alphabetical order where 'A' < 'B' < 'C').
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
The function iterates through all 100 rows of the 2D array StudentGrades. In each row, it checks if the Subject Code matches the search parameter. If it matches, the grade character is retrieved and compared to the target PassGrade. Since alphabetical order has 'A' < 'C', the condition CurrentGrade <= PassGrade successfully identifies grades that are equal to or better than the target pass grade. A running count is incremented and returned.
PastPaper.markingScheme
1 Mark: Function header with parameters and return type. 1 Mark: Initialise counter to 0. 2 Marks: Loop from 1 to 100 to check all rows. 2 Marks: Correct array indexing for SubjectCode (column 2) and Grade (column 3). 2 Marks: Correct comparison logic for grade hierarchy (e.g. CurrentGrade <= PassGrade). 1 Mark: Correctly incrementing and returning the count.
A linear queue is implemented as a 1D array QueueData of 50 elements (indexes 1 to 50), with two global integer pointers: HeadPointer (initially 1) and TailPointer (initially 0).
Write pseudocode for the procedure Enqueue which takes a string parameter NewItem and attempts to add it to the queue. If the queue is full, it should output 'Queue Overflow' and make no changes. Otherwise, update the TailPointer, place the item, and output 'Success'.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Before adding an item, we check if TailPointer has reached the upper boundary of the array (50). If so, queue is full ('Queue Overflow'). Otherwise, TailPointer is incremented by 1, and the NewItem is stored at QueueData[TailPointer]. A success message is printed.
PastPaper.markingScheme
1 Mark: Procedure header with correct parameter. 2 Marks: Correct check for overflow (TailPointer = 50 or TailPointer >= 50). 1 Mark: Outputting 'Queue Overflow' in the then-branch. 2 Marks: Correctly incrementing TailPointer by 1 inside the else-branch. 2 Marks: Correctly assigning NewItem to the array at the updated TailPointer. 1 Mark: Outputting 'Success' on successful insertion.
Write a pseudocode procedure SortScores that sorts a global 1D array Scores of 80 integers in descending order using an optimized bubble sort algorithm. The algorithm must terminate early if a pass is completed without any values being swapped.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
The optimized bubble sort uses a boolean flag (Swapped) initialized to FALSE before each pass. A nested loop compares adjacent elements. To sort in descending order, we check if Scores[Index] < Scores[Index+1] and swap if true, setting Swapped to TRUE. The limit is decremented by 1 after each pass to avoid unnecessary comparisons. The outer loop continues UNTIL Swapped is FALSE.
PastPaper.markingScheme
1 Mark: Procedure header. 1 Mark: Initialising boolean flag (Swapped) to FALSE before the inner loop. 2 Marks: Outer loop that repeats until no swaps are made. 1 Mark: Inner loop with correct bounds (1 to Limit, where Limit starts at 79). 2 Marks: Correct descending order comparison (Scores[Index] < Scores[Index + 1]). 2 Marks: Correct swap logic using a temporary variable. 1 Mark: Decrementing the comparison limit after each pass.
TYPE BookRecord DECLARE Title : STRING DECLARE Author : STRING DECLARE ISBN : STRING DECLARE CopyCount : INTEGER ENDTYPE
An array of 200 such records is declared as Library[1:200].
Write a pseudocode function FindAuthorBooks that takes a string SearchAuthor as a parameter. It must search through the array Library and output the title and ISBN of every book written by that author. The function must return the sum of CopyCount for all matching books. If no matching books are found, it should return 0.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
The function iterates from index 1 to 200 through the Library array. For each index, it accesses the Author field of the BookRecord using dot notation. If it matches SearchAuthor, it outputs the Title and ISBN fields, and adds the CopyCount to a running total. Finally, it returns this total copies value.
PastPaper.markingScheme
1 Mark: Function header with parameter and return type. 1 Mark: Initialising TotalCopies to 0. 2 Marks: Loop from 1 to 200. 2 Marks: Accessing fields of records correctly using dot notation (e.g. Library[Index].Author). 2 Marks: Logic to check matching author and outputting correct fields. 1 Mark: Returning the correct accumulated sum.
Write a pseudocode function ValidatePassword that takes a string Password and returns a boolean TRUE if it is valid, and FALSE otherwise.
A valid password must: - Be at least 8 characters long and no more than 15 characters long. - Contain at least one uppercase letter ('A' to 'Z'). - Contain at least one digit ('0' to '9'). - Not contain any spaces.
Use standard string functions: - LENGTH(Str) returns the length of Str. - MID(Str, Start, Length) returns a substring. - ASC(Char) returns the ASCII value of Char.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
First, the length is validated to be between 8 and 15 inclusive. Then, a loop iterates through each character. The ASCII value is used to check for uppercase characters (65 to 90) and digits (48 to 57), and a direct comparison checks for space. Finally, the function returns TRUE only if all conditions are satisfied.
PastPaper.markingScheme
1 Mark: Function header and return type. 1 Mark: Correctly checking length bounds (8 to 15) and returning FALSE if invalid. 2 Marks: Loop through every character of the string using LENGTH and MID. 2 Marks: Identifying uppercase letters correctly using ASCII (65 to 90). 2 Marks: Identifying digits correctly using ASCII (48 to 57). 1 Mark: Detecting spaces and returning overall boolean combination accurately.
Write a recursive pseudocode function GCD that implements the Euclidean algorithm to find the greatest common divisor of two positive integers X and Y. The mathematical definition is:
GCD(X, Y) = X if Y = 0 GCD(X, Y) = GCD(Y, X MOD Y) otherwise
Ensure your function includes correct parameter declarations, data types, base case, and recursive call.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
A recursive function GCD is declared with parameters X and Y as integers. The base case is when Y is equal to 0, which returns X. The recursive step calls GCD again, passing Y as the first argument and X MOD Y as the second argument, returning the result of this call.
PastPaper.markingScheme
2 Marks: Function header with two INTEGER parameters and INTEGER return type. 2 Marks: Base case condition (Y = 0) correctly checked. 2 Marks: Correct base case return value (X). 2 Marks: Correct recursive call format with modified parameters (Y, X MOD Y). 1 Mark: Returning the recursive call result.
A linked list is implemented using a global 1D array of records List[1:100] where each record has a Data field (STRING) and a Pointer field (INTEGER). The start of the list is pointed to by a global integer StartPointer. Empty nodes have their Pointer field set to -1, and the last item of the list also has its Pointer set to -1.
Write a pseudocode function SearchList that takes a parameter SearchItem (STRING) and performs a linear search through the active list. It must return the array index where the item is found, or -1 if the item is not in the list or if the list is empty.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
We initialize CurrentPointer with StartPointer. A loop runs as long as CurrentPointer is not -1. Inside the loop, we check if the Data field of the record at the current index matches SearchItem. If it does, we return CurrentPointer immediately. Otherwise, we advance CurrentPointer to the Pointer field of the current record. If the loop ends without finding the item, we return -1.
PastPaper.markingScheme
1 Mark: Function header with correct parameter and return type. 1 Mark: Initialize a traversal pointer with StartPointer. 2 Marks: Loop condition ensuring traversal stops when pointer is -1. 2 Marks: Correctly checking if data matches SearchItem using List[CurrentPointer].Data. 2 Marks: Correctly updating current pointer to List[CurrentPointer].Pointer. 1 Mark: Returning -1 if search fails after complete traversal.
Paper 32: Advanced Theory
Answer all questions. Calculators must not be used.
A real number is stored in a 12-bit normalized floating-point representation, using two's complement. The mantissa is stored in the first 8 bits (including the sign bit as the most significant bit). The exponent is stored in the remaining 4 bits. The binary point is placed immediately to the right of the sign bit in the mantissa.
(a) Show the normalized floating-point representation for the value -3.75 in this system. Show your working.
(b) Identify the minimum positive non-zero value that can be represented using this normalized 12-bit format. Show your working.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Part (a): 1. Convert -3.75 to binary. -3.75 = -15/4 = -15 * 2^(-2). 2. Express as a normalized fraction: -3.75 = -0.9375 * 2^2. The mantissa must represent -0.9375. 3. Positive 0.9375 = 0.1111000 in binary. 4. Convert to negative mantissa using two's complement: Invert bits of 0.1111000 to get 1.0000111, then add 1 to get 1.0001000. Thus, Mantissa = 10001000. 5. The exponent is +2. Convert +2 to 4-bit two's complement: 0010. 6. Combined representation: 10001000 0010.
Part (b): 1. For the minimum positive non-zero normalized number, the smallest possible positive normalized mantissa is 0.1000000 (which represents 0.5 in denary). 2. The smallest possible exponent in a 4-bit two's complement representation is -8 (which is 1000 in binary). 3. Calculate the value: 0.5 * 2^(-8) = 0.5 * (1/256) = 1/512 = 0.001953125.
PastPaper.markingScheme
Part (a) [4 marks]: - 1 mark: Correctly scaling the value to normalized form: -0.9375 * 2^2. - 1 mark: Correct conversion of positive 0.9375 to binary (0.1111000). - 1 mark: Correct two's complement representation for the negative mantissa (10001000). - 1 mark: Correct exponent conversion (+2 to 0010).
Part (b) [2.81 marks]: - 1 mark: Identifying that the smallest positive normalized mantissa is 0.1000000 (or 0.5). - 1 mark: Identifying that the smallest exponent is -8 (or 1000). - 0.81 mark: Calculating the correct final value as 1/512 or 0.001953125.
A doubly linked list is implemented using an Object-Oriented Programming language. Each node in the list is defined by a class Node with three attributes: Data (String), NextNode (Pointer to Node), and PrevNode (Pointer to Node).
The following incomplete pseudocode method InsertAfter is designed to insert a new node, NewNode, immediately after the current node (self):
PUBLIC PROCEDURE InsertAfter(NewNode : Node) NewNode.NextNode <- self.NextNode NewNode.PrevNode <- self IF self.NextNode <> NULL THEN // Missing Statement 1 ENDIF // Missing Statement 2 ENDPROC
(a) State the two missing statements to correctly update the pointers and insert the node.
(b) Explain the consequences of executing these statements in the incorrect order if Missing Statement 2 is executed before updating the next node's back pointer.
Part (b): - If self.NextNode is updated to point to NewNode before we set self.NextNode.PrevNode, then self.NextNode has already been changed to point to NewNode. - Attempting to execute self.NextNode.PrevNode <- NewNode afterwards would actually set NewNode.PrevNode <- NewNode, creating a self-referential loop and losing access to the rest of the list (orphaning the nodes that originally followed).
PastPaper.markingScheme
Part (a) [3 marks]: - 1.5 marks: Correctly identifying Statement 1 as self.NextNode.PrevNode <- NewNode. - 1.5 marks: Correctly identifying Statement 2 as self.NextNode <- NewNode.
Part (b) [3.81 marks]: - 1 mark: Explaining that self.NextNode is the only link to the rest of the list. - 1 mark: Stating that updating self.NextNode first causes a loss of reference to the original successor node. - 1.81 marks: Detailing the concrete outcome (e.g., self-reference loop on NewNode, or orphaning the remaining elements).
An expression parser evaluates infix expressions by converting them to Reverse Polish Notation (RPN).
Consider the following infix expression: (A + B) * (C - D / E)
(a) Convert this infix expression into its equivalent Reverse Polish Notation (RPN).
(b) Using the RPN expression from part (a), show the contents of the evaluation stack after each operator (+, /, -, *) is executed when the variables have the following values: A = 3, B = 5, C = 10, D = 8, E = 2.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Part (a): 1. The term (A + B) in RPN is A B +. 2. In (C - D / E), division has precedence over subtraction. So D / E becomes D E /. 3. The subtraction becomes C D E / -. 4. Multiplying both terms yields: A B + C D E / - *
Part (b): Substitute values: 3 5 + 10 8 2 / - * - Push 3, Push 5. - Execute +: Pop 5, Pop 3, Push 8. Stack contents: [8] - Push 10, Push 8, Push 2. - Execute /: Pop 2, Pop 8, Push 4. Stack contents: [8, 10, 4] - Execute -: Pop 4, Pop 10, Push 6 (derived from 10 - 4). Stack contents: [8, 6] - Execute *: Pop 6, Pop 8, Push 48. Stack contents: [48]
PastPaper.markingScheme
Part (a) [3 marks]: - 1 mark: Correct conversion of (A + B) to A B +. - 1 mark: Correct conversion of (C - D / E) to C D E / -. - 1 mark: Combining the elements correctly with '*' at the end.
Part (b) [3.81 marks]: - 1 mark: Correct stack state [8] after the first '+' operator. - 1 mark: Correct stack state [8, 10, 4] after the '/' operator. - 1 mark: Correct stack state [8, 6] after the '-' operator. - 0.81 mark: Correct final stack state [48] after the '*' operator.
Alice wants to send a confidential document to Bob over an insecure network. To guarantee both confidentiality and non-repudiation, she decides to use asymmetric encryption along with a digital signature.
Describe the steps Alice and Bob must perform to:
(a) Generate the digital signature for the document.
(b) Encrypt the combined document and signature to ensure confidentiality, and outline how Bob decrypts and verifies the message upon receipt.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Part (a): 1. Alice applies a cryptographic hashing algorithm (such as SHA-256) to the original document to produce a unique, fixed-size message digest. 2. Alice encrypts this message digest using her own private key. The resulting encrypted digest is her digital signature. 3. The digital signature is appended to the original document.
Part (b): 1. Alice encrypts the combined document and digital signature using Bob's public key to ensure confidentiality during transmission. 2. Bob receives the encrypted package and decrypts it using his own private key. 3. To verify authenticity and integrity: Bob decrypts the digital signature using Alice's public key to recover the original message digest. He also hashes the decrypted document using the same hashing algorithm. If the computed digest matches the decrypted digest, the signature is successfully verified.
PastPaper.markingScheme
Part (a) [3.81 marks]: - 1 mark: Hashing the original document to create a message digest. - 1.81 marks: Encrypting the message digest with Alice's private key to create the digital signature. - 1 mark: Appending the digital signature to the original document.
Part (b) [3 marks]: - 1 mark: Encrypting the entire package (document + signature) using Bob's public key. - 1 mark: Bob decrypting the package using his private key. - 1 mark: Bob decrypting the signature with Alice's public key and comparing it with the calculated hash of the decrypted document.
A compiler's syntax analyzer uses the following Backus-Naur Form (BNF) rules to parse a simplified variable declaration:
::= A | B | C ::= 0 | 1 | 2 ::= | | ::= INT | REAL ::= : ;
Identify whether each of the following expressions is valid or invalid based on these BNF rules. Explain your answers.
(a) A10 : INT ;
(b) C : REAL
(c) 1B : INT ;
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Part (a): - Valid. The token 'A10' is a valid because 'A' is a (hence an ). 'A1' is , making it an . 'A10' is , making it an . The type 'INT' is valid and it is terminated by ';'.
Part (b): - Invalid. The rule specifies that a declaration must end with a semicolon ';'. The string 'C : REAL' is missing this semicolon.
Part (c): - Invalid. The string '1B' begins with a digit. According to the recursive definition of , the leftmost character must always trace back to the base case, which is a . It is impossible to begin an identifier with a .
PastPaper.markingScheme
Part (a) [2 marks]: - 1 mark: Stating the expression is valid. - 1 mark: Explaining the recursive derivation of 'A10' starting with a letter.
Part (b) [2 marks]: - 1 mark: Stating the expression is invalid. - 1 mark: Pointing out the missing trailing semicolon (;).
Part (c) [2.81 marks]: - 1 mark: Stating the expression is invalid. - 1.81 marks: Explaining that the identifier starts with a digit ('1'), violating the rule that identifiers must originate from a as the base case.
A software development firm designs a virtual machine (VM) environment to execute intermediate bytecode rather than compile software directly to native machine code.
(a) Explain how a virtual machine provides platform independence for executing this bytecode.
(b) Describe two drawbacks of executing program code via a virtual machine compared to native execution.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Part (a): - The source code is compiled into an intermediate, platform-independent bytecode rather than target-specific machine code. - The virtual machine acts as an abstraction layer between the program bytecode and the computer hardware. - To run this code, any host operating system only needs an installation of the specific virtual machine runtime environment. The VM translates the intermediate bytecode into the host system's native machine code instructions in real time.
Part (b): - Drawback 1: Performance overhead. Interpreting bytecode or compiling it on-the-fly (Just-In-Time compilation) introduces a latency that is slower than running pre-compiled native machine instructions. - Drawback 2: Resource consumption. The virtual machine software itself requires memory and processing power to run, creating a higher system footprint than lightweight native binaries.
PastPaper.markingScheme
Part (a) [3.81 marks]: - 1 mark: Explaining that the compiler produces intermediate, platform-independent bytecode. - 1.81 marks: Describing the VM's role in translating this bytecode into hardware-specific native machine code at runtime. - 1 mark: Explaining that the application itself does not need to be compiled for different target architectures; only the VM environment must be ported.
Part (b) [3 marks]: - 1.5 marks: Identifying and explaining the degradation in execution speed/performance due to translation overhead. - 1.5 marks: Identifying and explaining the increased system/memory usage caused by running the VM layer itself.
Artificial Neural Networks (ANNs) are trained using backpropagation and gradient descent.
(a) Explain the term "backpropagation" in the context of training an Artificial Neural Network.
(b) State the role of an activation function in a neural network node and explain why non-linear activation functions are critical for deep neural networks.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Part (a): - Backpropagation is the process of calculating the gradient of the loss function with respect to the weights of the neural network. - After a forward pass where inputs produce a predicted output, the error (difference between predicted and target output) is computed. - This error is propagated backward through the network layers. The algorithm calculates the partial derivatives of the error (gradients) with respect to each weight and bias using the chain rule, allowing optimization algorithms (like gradient descent) to adjust the weights to minimize future error.
Part (b): - Role: It calculates the weighted sum of inputs plus bias and applies a mathematical function to determine the output of the node. - Necessity of non-linearity: Without non-linear activation functions, any multi-layer neural network collapses mathematically into a single-layer linear transformation. Non-linear activation functions allow the network to learn complex patterns and model non-linear relationships (e.g., solving the XOR problem).
PastPaper.markingScheme
Part (a) [3.81 marks]: - 1 mark: Stating that error is calculated at the output layer using a loss function. - 1.81 marks: Explaining that the error is propagated backward through the network layers to calculate gradients of weights/biases. - 1 mark: Identifying that these gradients are used to update weights (via gradient descent) to minimize error.
Part (b) [3 marks]: - 1.5 marks: Explaining that the activation function determines the output of a node based on its weighted inputs. - 1.5 marks: Explaining that non-linear activation functions are critical to allow the network to approximate complex non-linear functions (preventing it from collapsing to a simple linear model).
(a) Write down the output produced by the query: ?- route(london, rome). Explain the steps the Prolog interpreter takes to resolve this query.
(b) Write a new rule layover(X, Y, Z) that is true if there is a flight route from X to Y with a single intermediate layover at Z.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Part (a): - Output: true (or yes) - Step 1: Prolog attempts to resolve route(london, rome) using the first rule: route(X, Y) :- direct(X, Y). It checks the database for direct(london, rome). This fact does not exist, so it fails. - Step 2: Prolog moves to the second rule: route(X, Y) :- direct(X, Z), route(Z, Y). It binds X = london and searches for Z such that direct(london, Z) is true. It finds Z = paris (from direct(london, paris).). - Step 3: It sets up a sub-goal: route(paris, rome). It attempts to resolve route(paris, rome) using the first rule. It checks the database for direct(paris, rome), which exists as a fact. Therefore, route(paris, rome) evaluates to true, making route(london, rome) evaluate to true.
Part (b): - The rule must check that there is a direct connection from X to Z and a direct connection from Z to Y. - Rule: layover(X, Y, Z) :- direct(X, Z), direct(Z, Y).
PastPaper.markingScheme
Part (a) [3.81 marks]: - 1 mark: Stating the final output is true. - 1 mark: Explaining the first check for direct(london, rome) fails. - 1.81 marks: Explaining the recursive step of finding Z = paris and resolving route(paris, rome) which succeeds via direct(paris, rome).
Part (b) [3 marks]: - 1.5 marks: Correctly defining the relation head layover(X, Y, Z) :- . - 1.5 marks: Correctly linking the body conditions with a comma: direct(X, Z), direct(Z, Y).
An array-based data structure, DoubleStack, is designed to store two independent stacks, Stack A and Stack B, within a single one-dimensional array DataArray[0 : 99].
Stack A grows from index 0 upwards (towards 99). Pointer TopA stores the index of the top element of Stack A, and is initialized to -1. Stack B grows from index 99 downwards (towards 0). Pointer TopB stores the index of the top element of Stack B, and is initialized to 100.
(a) State the logical condition, using the pointers TopA and TopB, that indicates the entire DoubleStack is full and no further elements can be pushed onto either stack.
(b) Write pseudocode for the procedure PushA(Value) which attempts to add an element to Stack A. Your procedure must check for a full stack condition and output an appropriate error message if the stack is full.
(c) Suggest one advantage and one disadvantage of using this shared DoubleStack implementation compared to using two independent array-based stacks of size 50 each.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) The stacks grow towards each other. Stack A moves to the right (index increases) and Stack B moves to the left (index decreases). They meet and the array is full when the index immediately above TopA is occupied by TopB, which is represented by the expression: TopA + 1 = TopB.
(b) Pseudocode implementation: PROCEDURE PushA(Value) IF TopA + 1 = TopB THEN OUTPUT "Error: DoubleStack is full" ELSE TopA <- TopA + 1 DataArray[TopA] <- Value ENDIF ENDPROCEDURE
(c) Advantage: Memory efficiency and high flexibility. If Stack A needs 70 slots and Stack B only needs 10, both can fit within the single 100-slot array. With two independent stacks of size 50, Stack A would overflow even though empty memory is available in Stack B's pool. Disadvantage: Thread safety issues. In multi-threaded environments, synchronization is required on the shared array, leading to memory contention. Also, a memory-leak or infinite loop in one stack can exhaust the entire shared array, crashing or blocking the other stack's operation.
PastPaper.markingScheme
(a) [2 Marks] - 1 mark: Recognizing that the stacks meet when the pointers are adjacent. - 1 mark: Providing the correct logical equation: TopA + 1 = TopB (or TopA >= TopB - 1).
(b) [3 Marks] - 1 mark: Correct conditional check for full stack status (IF TopA + 1 = TopB). - 1 mark: Handling the overflow path correctly (outputting an error message and not modifying the stack). - 1 mark: Correctly incrementing TopA and setting DataArray[TopA] to Value in the success path.
(c) [2 Marks] - 1 mark: Describing a valid advantage, e.g., better memory utilization, flexibility, or prevention of premature overflow when one stack has low usage. - 1 mark: Describing a valid disadvantage, e.g., concurrency conflicts, potential for one stack's excessive growth to starve the other, or risk of data corruption due to pointer arithmetic errors.
(a) Explain why the assignment statement "a1 = a + b * a" is valid, by breaking down how the term "b * a" is derived from .
(b) Identify whether the assignment statement "ab = b1" is valid or invalid under these BNF rules. Justify your answer.
(c) Modify the BNF rule for so that a variable must start with a , but can now be followed by any number of or characters (including none).
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) To show the validity of "b * a" within "a + b * a": - The statement root matches ::= "=" . - The RHS expression "a + b * a" utilizes the rule ::= "+" , where "a" maps to and "b * a" maps to . - The term "b * a" is parsed via the recursive rule ::= "*" . - The left-hand term "b" resolves as -> -> -> -> "b". - The right-hand factor "a" resolves as -> -> -> "a". - Since all leaf terminals match the grammar, "b * a" is valid.
(b) "ab = b1" is invalid. The left-hand side variable is "ab". According to the rule ::= | , a variable must be either a single letter (a or b) or a single letter followed by a single digit (1 or 2). A sequence of two letters ("ab") is not permitted by this rule.
(c) To allow a variable to start with a followed by any number of or elements, we introduce left or right recursion: ::= | |
PastPaper.markingScheme
(a) [3 Marks] - 1 mark: Identifies the root expansion of "a + b * a" as ::= "+" , assigning "b * a" to the rule. - 1 mark: Traces the structure of "b * a" to ::= "*" . - 1 mark: Demonstrates resolving the operands "b" and "a" back to the base character terminals through -> -> .
(b) [2 Marks] - 1 mark: Correctly identifies the statement as "invalid". - 1 mark: Provides a clear justification referencing the syntax constraint, noting that consecutive letters (e.g., "ab") are not defined in the variable rule.
(c) [2 Marks] - 1 mark: Correct base case resolving to a single . - 1 mark: Correct recursive clause allowing successive or elements (e.g., ::= | | ).
A secure communications system uses asymmetric cryptography to verify the authenticity and integrity of software update files distributed to remote clients.
The distributing server performs the following steps before transmitting the software update: 1. Calculates a cryptographic hash of the software update file. 2. Encrypts this hash using its own private key to create a digital signature. 3. Transmits the software update file and the digital signature to the client.
(a) Explain why the hash is encrypted with the distributing server's private key, rather than its public key, to create the digital signature.
(b) Describe in detail how a client device uses the digital signature and the original software update file to verify both the authenticity and the integrity of the update.
(c) Explain the security consequence if a malicious third party manages to steal the distributing server's private key.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) Under asymmetric cryptography, what is encrypted with the private key can only be decrypted by the corresponding public key. Since the server's public key is widely known, anyone can decrypt the hash. The successful decryption using this public key proves the signature could only have been generated by the server (authenticity/non-repudiation). If the public key were used to encrypt, only the server could decrypt it, which does not allow public verification, and anyone could forge a signature.
(b) Complete verification process: 1. The client receives the update file and the digital signature. It decrypts the signature using the distributing server's public key to retrieve the original hash calculated by the server. 2. The client feeds the received software update file through the identical cryptographic hashing algorithm (e.g., SHA-256) to generate a local hash. 3. The client compares the decrypted hash with its locally calculated hash. 4. If both hashes are identical, integrity is confirmed (the file has not been altered in transit) and authenticity is confirmed (the signature was created by the server's private key).
(c) Security consequence: If an attacker steals the private key, they can generate valid digital signatures for arbitrary files. They could bundle malware, sign it with the stolen private key, and distribute it. Because the signatures are cryptographically valid, the clients' security systems will verify the signature using the legitimate public key, trust the malware, and execute it, leading to widespread system compromises.
PastPaper.markingScheme
(a) [2 Marks] - 1 mark: Explaining that the private key is held only by the server, so encrypting with it establishes authenticity and non-repudiation. - 1 mark: Explaining that using the public key would mean anyone could encrypt a hash (forgery), or that only the server could decrypt it (making public verification impossible).
(b) [3 Marks] - 1 mark: Decrypts the digital signature using the distributing server's public key to get the sender's hash. - 1 mark: Independently hashes the received software update using the same hashing algorithm. - 1 mark: Compares the two hashes; if identical, confirms both integrity (no tampering) and authenticity (proven source).
(c) [2 Marks] - 1 mark: Explaining that the malicious third party can sign rogue updates or malware with the stolen private key. - 1 mark: Explaining that client software will accept these compromised packages as genuine and install them, resulting in security breaches.
Paper 42: Practical
Complete all practical tasks in Python, Java, or Visual Basic. Save evidence screenshots.
3 PastPaper.question · 75 PastPaper.marks
PastPaper.question 1 · Practical
25 PastPaper.marks
An event ticketing system is being developed using object-oriented programming. You will write program code to implement the base class Ticket and its subclass ConcertTicket.
1. Create a new project. Save it as TicketSystem. 2. Define the class Ticket with the following private attributes: - TicketID (string, e.g., "T001") - BasePrice (real, e.g., 45.00) - SeatNumber (string, e.g., "A12")
Implement the following methods in the Ticket class: - A constructor that accepts parameters to initialise all three attributes. - Getters for TicketID, BasePrice, and SeatNumber. - A method CalculatePrice() that returns the BasePrice.
3. Define the subclass ConcertTicket that inherits from Ticket and has the following additional private attributes: - Artist (string, e.g., "The Beets") - IsVIP (boolean, e.g., True)
Implement the following methods in the ConcertTicket class: - A constructor that accepts parameters to initialise all inherited and new attributes. - A getter for Artist and IsVIP. - An overridden method CalculatePrice() that returns the total price. If IsVIP is True, add 50.00 to the BasePrice. Otherwise, add a standard booking fee of 5.00 to the BasePrice.
4. In the main program: - Declare an array/list TicketArray of size 10 to store Ticket objects. - Write a procedure ReadData() that: - Opens the text file "tickets.txt". - Reads each line, parses the values, instantiates the appropriate object (Ticket or ConcertTicket), and inserts it into TicketArray. - Handles potential file-not-found errors gracefully. - Write a function SummariseTickets() that: - Iterates through the populated items in TicketArray. - Prints the TicketID, SeatNumber, and the calculated price for each ticket. - Calculates and returns the total price of all tickets in the array. - Write main execution code that calls ReadData(), calls SummariseTickets(), and prints the total revenue returned by the function.
Save your program code.
Create the text file tickets.txt in the same directory as your program with the following content: Ticket,T001,45.00,A12 Concert,T002,60.00,B14,The Beets,TRUE Ticket,T003,30.00,C01 Concert,T004,80.00,VIP1,The Beets,TRUE Concert,T005,50.00,A02,Electric Ants,FALSE
Run your program, take a screenshot of the console output, and include it in your evidence.
def ReadData(): try: with open("tickets.txt", "r") as file: index = 0 for line in file: if index >= 10: break parts = line.strip().split(",") if len(parts) < 4: continue ticket_type = parts[0] ticket_id = parts[1] base_price = float(parts[2]) seat_number = parts[3]
if ticket_type == "Ticket": TicketArray[index] = Ticket(ticket_id, base_price, seat_number) elif ticket_type == "Concert": artist = parts[4] is_vip = parts[5].upper() == "TRUE" TicketArray[index] = ConcertTicket(ticket_id, base_price, seat_number, artist, is_vip) index += 1 except FileNotFoundError: print("Error: tickets.txt not found.")
def SummariseTickets(): total_price = 0.0 for ticket in TicketArray: if ticket is not None: price = ticket.CalculatePrice() print(f"Ticket ID: {ticket.GetTicketID()} | Seat: {ticket.GetSeatNumber()} | Calculated Price: ${price:.2f}") total_price += price return total_price
# Main execution program ReadData() total = SummariseTickets() print(f"Total revenue: ${total:.2f}") ```
PastPaper.markingScheme
- Define base class `Ticket` with three private attributes: [2 marks] - `Ticket` constructor initialising parameters: [2 marks] - `Ticket` getters for `TicketID`, `BasePrice`, `SeatNumber`: [1 mark] - `Ticket` `CalculatePrice()` returning `BasePrice`: [1 mark] - Define subclass `ConcertTicket` with correct inheritance syntax: [1 mark] - `ConcertTicket` private attributes `Artist` and `IsVIP`: [1 mark] - `ConcertTicket` constructor calling the superclass constructor: [2 marks] - `ConcertTicket` `CalculatePrice()` implementation with correct conditions (adds 50.00 if VIP, otherwise 5.00): [3 marks] - Declare 1D array `TicketArray` of size 10 to store `Ticket` objects: [1 mark] - Write `ReadData()` with exception handling for file-not-found: [2 marks] - `ReadData()` reads and splits data, instantiating `Ticket` or `ConcertTicket` polymorphically: [3 marks] - Write `SummariseTickets()` iterating through array and calling polymorphic methods: [3 marks] - `SummariseTickets()` returns the accurate total sum ($370.00): [2 marks] - Output screenshot shows correct formatting and expected output values: [1 mark]
PastPaper.question 2 · Practical
25 PastPaper.marks
An ordered linked list can be implemented using a 1D array of node objects.
You will write program code to implement an ordered linked list that stores integers in ascending numerical order.
1. Create a new project. Save it as OrderedLinkedList. 2. Define a class Node with the following private attributes: - Data (integer) - NextNode (integer, acting as a pointer to the index of the next node)
Implement the following methods in the Node class: - A constructor that accepts parameters to initialise Data and NextNode. - Getters and setters for both attributes.
3. Define a class LinkedList with the following private attributes: - List (an array of 10 Node objects) - StartPointer (integer) - FreePointer (integer)
Implement the following methods in the LinkedList class: - A constructor that: - Initialises all 10 elements in List as a chain of free nodes (index 0 points to 1, 1 points to 2, ..., 8 points to 9, and index 9 points to -1). Data values should default to 0. - Sets StartPointer to -1. - Sets FreePointer to 0. - A method Insert(NewValue : integer) that: - Returns False if there is no free space in the list. - Inserts NewValue into the correct sorted position in the list (ascending order). - Updates StartPointer, FreePointer, and the pointers of the affected nodes. - Returns True if successfully inserted. - A method PrintList() that: - Traverses the linked list starting from StartPointer and prints each Data value in order. - If the list is empty, outputs an appropriate message.
4. Write a main program to: - Instantiate an object of LinkedList. - Insert the values: 15, 5, 20, 10 in that order. - Call PrintList() to display the contents. - Try inserting 7 more values to fill the list, then attempt one more insertion to demonstrate the list is full, printing the boolean return value of the insertion.
Save your program code, run it, and include a screenshot of the console output as evidence.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
```python class Node: def __init__(self, data=0, next_node=-1): self.__Data = data self.__NextNode = next_node
# Insert into sorted list if self.__StartPointer == -1 or NewValue < self.__List[self.__StartPointer].GetData(): self.__List[newNodeIndex].SetNextNode(self.__StartPointer) self.__StartPointer = newNodeIndex else: current = self.__StartPointer previous = -1 while current != -1 and self.__List[current].GetData() < NewValue: previous = current current = self.__List[current].GetNextNode()
def PrintList(self): if self.__StartPointer == -1: print("The list is empty.") return
current = self.__StartPointer while current != -1: print(self.__List[current].GetData(), end=" -> ") current = self.__List[current].GetNextNode() print("None")
- Define class `Node` with private attributes: [1 mark] - `Node` constructor with default parameters: [1 mark] - `Node` getters and setters: [2 marks] - Define class `LinkedList` with attributes `List`, `StartPointer`, `FreePointer`: [1 mark] - `LinkedList` constructor initialises array of 10 nodes linked sequentially: [2 marks] - `LinkedList` constructor sets pointers correctly: [1 mark] - `Insert()` checks if list is full and returns `False`: [1 mark] - `Insert()` retrieves index from free list and updates `FreePointer` pointer: [2 marks] - `Insert()` inserts at empty list / start of list: [3 marks] - `Insert()` traverses list to find sorted ascending index: [3 marks] - `Insert()` updates pointers of prior node and current node correctly: [2 marks] - `PrintList()` traverses list starting from `StartPointer` printing contents: [2 marks] - Main program instantiates `LinkedList` and inserts: 15, 5, 20, 10: [1 mark] - Main program executes `PrintList()` and demonstrates correct output sorting: [1 mark] - Main program tests full-list condition and outputs return value (`False`): [2 marks]
PastPaper.question 3 · Practical
25 PastPaper.marks
A Binary Search Tree (BST) stores character strings in alphabetical order.
You will write program code to implement the binary search tree using a 1D array of 15 node objects.
1. Create a new project. Save it as BinaryTreeSystem. 2. Define a class TreeNode with the following private attributes: - Data (string) - LeftPointer (integer, pointer to the left child node index) - RightPointer (integer, pointer to the right child node index)
Implement the following methods in the TreeNode class: - A constructor that initialises Data to a blank string, and both pointers to -1. - Getters and setters for all three attributes.
3. Define a class BinaryTree with the following private attributes: - Tree (an array of 15 TreeNode objects) - RootPointer (integer) - FreePointer (integer)
Implement the following methods in the BinaryTree class: - A constructor that: - Initialises all 15 elements in Tree to a chain of free nodes (i.e., node index 0's LeftPointer points to 1, 1 points to 2, ..., 13 points to 14, and index 14's LeftPointer points to -1). Data values should be empty and RightPointer set to -1. - Sets RootPointer to -1. - Sets FreePointer to 0. - A method InsertNode(NewData : string) that: - Checks if FreePointer is -1. If so, outputs "Tree is full" and returns. - Retrieves the next free node from FreePointer, updates FreePointer to the node's LeftPointer. - Sets the new node's attributes (Data = NewData, LeftPointer = -1, RightPointer = -1). - If RootPointer is -1, sets RootPointer to this new node index. - Otherwise, traverses the tree from RootPointer to find the correct insertion position (alphabetical sorting). Updates the appropriate left or right pointer of the parent node to point to the new node. - A recursive method InOrder(CurrentPointer : integer) that: - Traverses and prints the contents of the tree in alphabetical order. - A getter method GetRootPointer() that returns RootPointer.
4. Write a main program to: - Instantiate an object of BinaryTree. - Insert the following words: "Mango", "Banana", "Pineapple", "Apple", "Orange", "Coconut". - Call the InOrder traversal method starting from the root node to print all contents in alphabetical order.
Save your program code, run it, and include a screenshot of the console output as evidence.
class BinaryTree: def __init__(self): self.__Tree = [TreeNode() for _ in range(15)] for i in range(14): self.__Tree[i].SetLeftPointer(i + 1) self.__Tree[14].SetLeftPointer(-1) self.__RootPointer = -1 self.__FreePointer = 0
if self.__RootPointer == -1: self.__RootPointer = newNodeIndex else: current = self.__RootPointer inserted = False while not inserted: if NewData < self.__Tree[current].GetData(): if self.__Tree[current].GetLeftPointer() == -1: self.__Tree[current].SetLeftPointer(newNodeIndex) inserted = True else: current = self.__Tree[current].GetLeftPointer() else: if self.__Tree[current].GetRightPointer() == -1: self.__Tree[current].SetRightPointer(newNodeIndex) inserted = True else: current = self.__Tree[current].GetRightPointer()
def InOrder(self, CurrentPointer): if CurrentPointer != -1: self.InOrder(self.__Tree[CurrentPointer].GetLeftPointer()) print(self.__Tree[CurrentPointer].GetData()) self.InOrder(self.__Tree[CurrentPointer].GetRightPointer())
# Main execution tree = BinaryTree() words = ["Mango", "Banana", "Pineapple", "Apple", "Orange", "Coconut"] for word in words: tree.InsertNode(word)
tree.InOrder(tree.GetRootPointer()) ```
PastPaper.markingScheme
- Define class `TreeNode` with three private attributes: [1 mark] - `TreeNode` constructor setting default values: [1 mark] - `TreeNode` getters and setters: [2 marks] - Define class `BinaryTree` with array `Tree` of 15 elements: [1 mark] - `BinaryTree` constructor linking free nodes sequentially via `LeftPointer`: [2 marks] - `BinaryTree` constructor setting correct pointer states: [1 mark] - `InsertNode()` checks for space limits: [1 mark] - `InsertNode()` updates `FreePointer` correctly: [2 marks] - `InsertNode()` initialises node contents: [1 mark] - `InsertNode()` handles root insertion: [1 mark] - `InsertNode()` loops and compares string values alphabetically: [3 marks] - `InsertNode()` connects node as left or right child when an empty slot is reached: [3 marks] - `InOrder()` recursive method base case checked: [1 mark] - `InOrder()` recursive calls for left and right pointer nodes: [2 marks] - `InOrder()` prints data value in correct position (infix): [1 mark] - Main program instantiates and inserts words: [1 mark] - Main program successfully calls `InOrder()` to print terms alphabetically: [1 mark]