An original Thinka practice paper modelled on the structure and difficulty of the Nov 2023 (V2) 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.
9 PastPaper.question · 65 PastPaper.marks
PastPaper.question 1 · shortAnswer
4 PastPaper.marks
Describe how overflow can be detected when two signed 8-bit binary integers, represented in two's complement, are added together.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
In signed 8-bit two's complement representation, the range of valid values is from \(-128\) to \(+127\). If the result of an addition falls outside this range, overflow occurs. This can only happen when adding two positive numbers (which might yield an invalid negative result) or two negative numbers (which might yield an invalid positive result). Adding a positive and a negative number can never overflow. On a hardware level, this is detected by comparing the carry bit entering the sign bit (MSB) and the carry bit leaving the sign bit; if they do not match, overflow has occurred.
PastPaper.markingScheme
1 mark: State that overflow occurs when the range of the representation (\(-128\) to \(+127\)) is exceeded. 1 mark: Explain that overflow is impossible when adding numbers of opposite signs. 1 mark: Explain that overflow can only occur when adding two positive or two negative numbers. 1 mark: State that overflow is detected if the sign of the result is different from the sign of the two operands (or when the carry into the MSB is different from the carry out of the MSB).
PastPaper.question 2 · shortAnswer
4 PastPaper.marks
A web application requires user validation (such as checking if an email contains the '@' symbol) and database querying (such as checking if the email already exists in a database). Identify which of these tasks is best suited for client-side scripting and which is best suited for server-side scripting, and explain why for each.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Client-side scripting runs on the user's browser, making it ideal for immediate input validation like format checks (presence of '@') because it responds quickly without a network round-trip. Server-side scripting runs on the web server, which has secure direct access to the database. Querying the database must happen server-side because the database credentials and internal structures must not be exposed to the client, preventing SQL injection and unauthorized data access.
PastPaper.markingScheme
1 mark: Identify email validation as client-side and database querying as server-side. 1 mark: Explain that client-side validation gives immediate feedback and reduces unnecessary server requests. 1 mark: Explain that database querying must be server-side because the client browser cannot have direct database access for security reasons. 1 mark: Explain that server-side scripts can securely query database management systems using protected credentials.
PastPaper.question 3 · shortAnswer
4 PastPaper.marks
Explain the specific roles of, and relationship between, the Program Counter (PC) and the Memory Address Register (MAR) during the fetch stage of the fetch-decode-execute cycle.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
At the beginning of the fetch stage, the Program Counter (PC) holds the memory address of the next instruction to be fetched and executed. This address is copied from the PC to the Memory Address Register (MAR) via the internal data bus. While the MAR uses this address to fetch the instruction from main memory via the address bus, the PC is simultaneously incremented by one so that it points to the next consecutive instruction in memory.
PastPaper.markingScheme
1 mark: State that the PC holds the address of the next instruction to be fetched. 1 mark: Explain that the address in the PC is copied to the MAR at the start of the fetch cycle. 1 mark: Explain that the PC is incremented to point to the next instruction. 1 mark: State that the MAR holds the address of the memory location currently being read from and sends this address onto the address bus.
PastPaper.question 4 · shortAnswer
4 PastPaper.marks
Explain two reasons why a software developer would prefer to use an interpreter rather than a compiler during the development and debugging phase of a program.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
During development, an interpreter is preferred because it translates and executes source code line-by-line without producing a standalone executable file first. First, this enables immediate execution and testing after a change is made, avoiding the time-consuming process of recompiling the whole source code. Second, when an error is encountered during runtime, the interpreter stops execution instantly at that exact line and reports the error location, making debugging much faster and more precise than resolving errors from a compiler's error list.
PastPaper.markingScheme
1 mark: State that interpreters do not require a complete recompilation step before running. 1 mark: Explain that this saves time by allowing immediate execution and testing of code changes. 1 mark: State that interpreters execute line-by-line and halt immediately when an error is encountered. 1 mark: Explain that this provides precise, real-time error messages pointing to the exact line of code, simplifying debugging.
PastPaper.question 5 · shortAnswer
4 PastPaper.marks
Describe what is meant by 'referential integrity' in a relational database and explain how it is enforced using primary keys and foreign keys.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Referential integrity is a database state where all foreign key values are valid and point to existing, correct primary keys in parent tables, preventing orphaned records. To enforce this, a primary key uniquely identifies a record in the parent table. A foreign key is established in the related child table to link back to this primary key. The database management system (DBMS) enforces referential integrity by rejecting any database action (such as inserting a foreign key value that does not exist as a primary key, or deleting a parent record that still has associated child records) that would break this link.
PastPaper.markingScheme
1 mark: Define referential integrity as maintaining the consistency of relationships between tables / ensuring no orphaned records exist. 1 mark: Explain that a primary key uniquely identifies records in a parent table, while a foreign key links to this key from a child table. 1 mark: Explain that any foreign key value must match an existing primary key value (or be null). 1 mark: Explain that the DBMS enforces this by preventing invalid inserts, updates, or deletions that would break the link.
PastPaper.question 6 · structuredDescription
10 PastPaper.marks
A multimedia company is recording a high-fidelity digital audio stream. (a) Define the terms 'sampling rate' and 'sampling resolution', and describe their effect on the quality of the recorded sound and the resulting file size. [4] (b) Calculate the exact file size in bytes for a 30-second stereo (2 channels) audio clip recorded with a sampling rate of 44,100 Hz and a sampling resolution of 16 bits. Show your working. [3] (c) Explain the difference between lossy and lossless compression when applied to audio files, and identify one file format associated with each. [3]
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) Sampling rate is the number of sound samples captured per second, measured in Hertz (Hz). Sampling resolution (bit depth) is the number of bits used to store each sample. Increasing either improves sound quality as it approximates the original analogue wave more closely, but it increases the final file size because more data points are recorded and stored per second. (b) File size calculation: Duration = 30 seconds, Sampling Rate = 44,100 Hz, Sampling Resolution = 16 bits, Channels = 2. Total bits = \(30 \times 44,100 \times 16 \times 2 = 42,336,000\) bits. To convert to bytes: \(42,336,000 / 8 = 5,292,000\) bytes. (c) Lossy compression permanently discards less audible sound data (such as frequencies beyond human hearing) to achieve a highly reduced file size, but slightly reduces audio quality (example: MP3). Lossless compression reduces file size by reorganizing/compressing data without deleting any information, allowing the original audio to be reconstructed perfectly (example: FLAC).
PastPaper.markingScheme
(a) [Max 4 marks]: 1 mark for defining sampling rate. 1 mark for defining sampling resolution. 1 mark for explaining quality improvement. 1 mark for explaining file size increase. (b) [Max 3 marks]: 1 mark for correct formula/substituted values. 1 mark for correct calculation in bits (42,336,000). 1 mark for correct conversion to bytes (5,292,000 bytes). (c) [Max 3 marks]: 1 mark for describing lossy compression with a valid example (e.g. MP3 / AAC). 1 mark for describing lossless compression with a valid example (e.g. FLAC / ALAC). 1 mark for identifying the key difference (lossy permanently deletes data, lossless retains all original data).
PastPaper.question 7 · structuredDescription
10 PastPaper.marks
The fetch stage of the Fetch-Execute cycle can be described using Register Transfer Notation (RTN). (a) Write the step-by-step fetch stage of the Fetch-Execute cycle using standard Register Transfer Notation (RTN). [4] (b) Describe the role of the Program Counter (PC) and the Memory Data Register (MDR) during the Fetch-Execute cycle. [4] (c) Explain how the CPU handles an interrupt occurring at the end of a Fetch-Execute cycle. [2]
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) Step 1: MAR <- [PC]. Step 2: PC <- [PC] + 1. Step 3: MDR <- [[MAR]]. Step 4: CIR <- [MDR]. (b) (i) Program Counter (PC) holds the memory address of the next instruction to be fetched. It is incremented in each fetch cycle so it points to the subsequent instruction. (ii) Memory Data Register (MDR) acts as a temporary buffer that holds the data or instruction fetched from memory (at the address in the MAR), or holds data waiting to be written to memory. (c) At the end of the Fetch-Execute cycle, the CPU checks for an interrupt signal. If an interrupt is detected, the CPU suspends the current program, saves the contents of current registers (including the PC) onto a stack, loads the memory address of the Interrupt Service Routine (ISR) into the PC to execute it, and restores the saved registers once the ISR is complete to resume the original program.
PastPaper.markingScheme
(a) [Max 4 marks]: 1 mark for MAR <- [PC]. 1 mark for PC <- [PC] + 1. 1 mark for MDR <- [[MAR]] (or MDR <- [Memory]). 1 mark for CIR <- [MDR]. (b) [Max 4 marks]: 1 mark for PC holding address of next instruction. 1 mark for PC incrementing. 1 mark for MDR holding fetched data/instruction. 1 mark for MDR acting as buffer for read/write operations. (c) [Max 2 marks]: 1 mark for checking interrupt flag at the end of the cycle and saving registers/PC on a stack. 1 mark for loading the Interrupt Service Routine (ISR) address into PC and executing it, then restoring registers.
PastPaper.question 8 · structuredDescription
10 PastPaper.marks
A school database currently has an unnormalised table: STUDENT_CLASSES(StudentID, StudentName, ClassID, ClassRoom, TeacherID, TeacherName, DateEnrolled). Each student can enroll in multiple classes. Each class is taught by exactly one teacher in a specific classroom. A teacher has a unique TeacherID and exactly one TeacherName. (a) Describe how this database table can be normalised to Third Normal Form (3NF). List the resulting tables, showing the fields and clearly identifying the primary keys and foreign keys. [5] (b) Write SQL commands to: (i) Create a table for TEACHER with fields TeacherID (integer, Primary Key) and TeacherName (variable-length string up to 50 characters, which cannot be null). [3] (ii) Write a SELECT query to find the names of all teachers who teach in room 'R101', assuming a table CLASS exists with fields ClassID, ClassRoom, and TeacherID. [2]
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) To convert to 3NF, we must remove partial and transitive dependencies. The resulting 3NF tables are: 1. STUDENT(StudentID, StudentName) where StudentID is Primary Key. 2. TEACHER(TeacherID, TeacherName) where TeacherID is Primary Key. 3. CLASS(ClassID, ClassRoom, TeacherID) where ClassID is Primary Key and TeacherID is Foreign Key referencing TEACHER. 4. ENROLLMENT(StudentID, ClassID, DateEnrolled) where (StudentID, ClassID) forms the composite Primary Key, and StudentID, ClassID are Foreign Keys. (b) (i) CREATE TABLE TEACHER (TeacherID INT PRIMARY KEY, TeacherName VARCHAR(50) NOT NULL); (ii) SELECT TEACHER.TeacherName FROM TEACHER INNER JOIN CLASS ON TEACHER.TeacherID = CLASS.TeacherID WHERE CLASS.ClassRoom = 'R101';
PastPaper.markingScheme
(a) [Max 5 marks]: 1 mark for STUDENT table with correct PK. 1 mark for TEACHER table with correct PK. 1 mark for CLASS table with correct PK and TeacherID as FK. 1 mark for ENROLLMENT table with correct composite PK and FKs. 1 mark for correct identification of all primary and foreign keys. (b) (i) [Max 3 marks]: 1 mark for CREATE TABLE TEACHER. 1 mark for TeacherID INT PRIMARY KEY. 1 mark for TeacherName VARCHAR(50) NOT NULL. (ii) [Max 2 marks]: 1 mark for SELECT TeacherName FROM TEACHER and CLASS (or JOIN structure). 1 mark for correct join condition and WHERE clause (CLASS.ClassRoom = 'R101').
PastPaper.question 9 · diagramAndConversions
15 PastPaper.marks
### Part (a) 1. Convert the denary value 409 into its 12-bit Binary Coded Decimal (BCD) representation. [2] 2. Explain one advantage of using BCD instead of standard binary representation for digital screen displays. [2] 3. Convert the hexadecimal value A7 into its denary representation. [1]
### Part (b) A continuous analogue sound wave is converted to digital form by an Analogue-to-Digital Converter (ADC). The sound wave is sampled with a 4-bit sampling resolution. The first four sampled values are: 3, 7, 12, and 10.
1. Convert these four sample values into their 4-bit binary equivalents. [2] 2. Describe the effect on the quality of the recorded sound and the resulting file size if the sampling rate is doubled and the sampling resolution is increased from 4 bits to 8 bits. [2] 3. Calculate the file size, in kilobytes (KB), of a monophonic sound recording with the following specifications: - Duration: 20 seconds - Sampling rate: 44 kHz - Sampling resolution: 16 bits Show your working. Use 1 KB = 1000 bytes. [2]
### Part (c) Run-Length Encoding (RLE) is a lossless compression technique. The first row of a black-and-white grid-based icon consists of the following sequence of pixels: `W W W B B B B W` (where W = White, B = Black)
1. Represent this row using Run-Length Encoding (RLE) in the format . [2] 2. Explain one situation where RLE would be highly effective for compressing an image, and one situation where it would be ineffective. [2]
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
### Part (a) 1. To convert \(409\) to BCD, we represent each decimal digit separately using 4 binary bits: - \(4 = 0100\) - \(0 = 0000\) - \(9 = 1001\) - Combined: \(0100\ 0000\ 1001\) 2. An advantage is that BCD makes it easy to map digits directly onto physical screens (e.g. seven-segment digital displays). There is no need for CPU-intensive mathematical division-by-ten operations to separate digits before displaying them. 3. To convert hexadecimal \(\text{A7}\) to denary: - \(\text{A} = 10\) - \(10 \times 16 + 7 \times 1 = 160 + 7 = 167\)
### Part (b) 1. Converting sample values to 4-bit binary equivalents: - \(3 = 0011\) - \(7 = 0111\) - \(12 = 1100\) - \(10 = 1010\) 2. Effect on sound quality: Increased sampling rate takes more frequent samples, capturing high frequencies more accurately. Increased sampling resolution reduces quantization noise, representing amplitude changes with greater precision. Effect on file size: Both changes increase the data captured per second, which increases overall file size. 3. Calculation of file size: - \(\text{Total bits} = \text{Duration (seconds)} \times \text{Sampling rate (Hz)} \times \text{Sampling resolution (bits)}\) - \(\text{Total bits} = 20 \times 44,000 \times 16 = 14,080,000\text{ bits}\) - \(\text{Total bytes} = 14,080,000 / 8 = 1,760,000\text{ bytes}\) - \(\text{Total KB} = 1,760,000 / 1000 = 1760\text{ KB}\)
### Part (c) 1. Group consecutive pixels into runs: - Three White pixels: \(\) - Four Black pixels: \(\) - One White pixel: \(\) - Representation: \(, , \) 2. RLE is effective when the source file has long repeating runs of identical characters/pixels (e.g., solid clipart, diagrams). It is ineffective when characters or colors rarely repeat consecutively (e.g., photographies/textures) since writing the color metadata alongside a count of 1 for almost every pixel can actually double the file size.
PastPaper.markingScheme
### Part (a) [5 Marks] 1. **[2 Marks]** BCD conversion: - 1 mark for any two digits converted correctly. - 1 mark for fully correct representation: `0100 0000 1001` (spaces optional). 2. **[2 Marks]** BCD advantage: - 1 mark for stating that each denary digit maps directly to its own group of 4 bits. - 1 mark for explaining that it makes display circuit decoding (e.g., 7-segment display) simpler or avoids mathematical division-by-ten algorithms. 3. **[1 Mark]** Hex conversion: - 1 mark for correct denary value: `167`.
### Part (b) [6 Marks] 1. **[2 Marks]** Binary equivalents: - 1 mark for any two/three correct conversions. - 2 marks for all four correct conversions: `0011`, `0111`, `1100`, `1010`. 2. **[2 Marks]** Rate/resolution effect: - 1 mark for stating that quality/fidelity is improved (closer to original sound wave, reduced quantization error). - 1 mark for stating that the resulting file size increases. 3. **[2 Marks]** Calculations: - 1 mark for showing correct working (e.g., calculating total bits as \(20 \times 44000 \times 16\) or converting intermediate values to bytes). - 1 mark for final correct answer of `1760` (KB).
### Part (c) [4 Marks] 1. **[2 Marks]** RLE representation: - 1 mark for a partially correct run representation (at least one sequence correct). - 2 marks for the correct run representation: `, , ` or equivalent (such as `W3B4W1`). 2. **[2 Marks]** RLE assessment: - 1 mark for stating it is effective for images with long runs of identical colors / solid backgrounds / simple vector graphics. - 1 mark for stating it is ineffective for photographic images with many varying continuous colors / gradients.
Paper 2 (Fundamental Problem-solving and Programming Skills)
Answer all questions. Use the recommended pseudocode conventions.
7 PastPaper.question · 58 PastPaper.marks
PastPaper.question 1 · identifierAndEvaluation
8 PastPaper.marks
An algorithm is written in pseudocode to analyze a string of characters and determine the length of the longest run of consecutive identical characters.
IF LENGTH(DataString) > 0 THEN MaxRun <- 1 FOR Index <- 1 TO LENGTH(DataString) - 1 ThisChar <- MID(DataString, Index, 1) NextChar <- MID(DataString, Index + 1, 1) IF ThisChar = NextChar THEN CurrentRun <- CurrentRun + 1 IF CurrentRun > MaxRun THEN MaxRun <- CurrentRun ENDIF ELSE CurrentRun <- 1 ENDIF NEXT Index ENDIF
RETURN MaxRun ENDFUNCTION
(a) Identify three variable identifiers declared in the function AnalyzeSequence, stating the data type of each. (b) Evaluate the output of AnalyzeSequence for each of the following function calls: (i) AnalyzeSequence("PQQQQR") (ii) AnalyzeSequence("") (c) Evaluate how the behavior of the algorithm changes if the line 'CurrentRun <- 1' in the ELSE block is omitted. Explain the impact on the final returned value.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Detailed Walkthrough:
- Part (a): Any three of the five declared variables inside the function are correct. For example, 'MaxRun', 'CurrentRun', and 'Index' are declared as INTEGER. 'ThisChar' and 'NextChar' are declared as CHAR.
- Part (b)(i): Calling AnalyzeSequence with "PQQQQR" iterates through the string. At index 2, 3, and 4, 'Q' matches the next character 'Q', incrementing CurrentRun to 2, 3, and then 4. MaxRun is updated to 4. At index 5, 'Q' does not equal 'R', so CurrentRun resets to 1. The maximum run is 4.
- Part (b)(ii): Calling AnalyzeSequence with an empty string "" results in LENGTH(DataString) evaluating to 0. The IF condition is false, bypassing the loop. MaxRun (initialized to 0) is returned.
- Part (c): The omission of 'CurrentRun <- 1' prevents the run counter from resetting when characters change. This is a logical error because once a sequence of duplicate letters ends, the algorithm must restart counting from 1 for the next distinct character sequence. If omitted, the count continues accumulating erroneously across different characters.
PastPaper.markingScheme
Part (a) [3 Marks]: - 1 mark per correct identifier paired with its correct data type (up to a maximum of 3 marks). Accept: MaxRun (INTEGER), CurrentRun (INTEGER), Index (INTEGER), ThisChar (CHAR), NextChar (CHAR).
Part (b) [2 Marks]: - 1 mark for evaluating AnalyzeSequence("PQQQQR") as 4. - 1 mark for evaluating AnalyzeSequence("") as 0.
Part (c) [3 Marks]: - 1 mark for stating that CurrentRun will not reset to 1 when a run ends / characters change. - 1 mark for stating that subsequent identical consecutive characters will continue to accumulate / increment the count from its previous value. - 1 mark for stating that this results in an incorrect, inflated MaxRun value being returned.
PastPaper.question 2 · identifierAndEvaluation
8 PastPaper.marks
A programmer is designing a module to process an array of 100 exam scores. The function ProcessScores takes an array Scores (indexed from 1 to 100) and an integer Target, and calculates the average of all scores strictly greater than the target.
FUNCTION ProcessScores(Scores : ARRAY, Target : INTEGER) RETURNS REAL DECLARE Total : INTEGER DECLARE Count : INTEGER DECLARE Index : INTEGER DECLARE Average : REAL
Total <- 0 Count <- 0
FOR Index <- 1 TO 100 IF Scores[Index] > Target THEN Total <- Total + Scores[Index] Count <- Count + 1 ENDIF NEXT Index
Average <- Total / Count RETURN Average ENDFUNCTION
(a) Identify the identifier used as the loop counter, and the identifier used as the accumulator, stating the data type of each. (b) Evaluate the behavior of the function if all 100 elements in the Scores array are less than or equal to Target. State the exact runtime error that would occur and reference the line of code responsible. (c) Propose a modification to the pseudocode to handle this scenario safely, showing the modified lines of code.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Detailed Walkthrough:
- Part (a): The loop counter 'Index' is declared as INTEGER and controls the FOR loop from 1 to 100. The accumulator 'Total' is used to sum the scores that exceed the target.
- Part (b): When all array elements are less than or equal to Target, the condition inside the IF statement is never met. Therefore, 'Count' is never incremented and remains 0. When 'Average <- Total / Count' is reached, the operation evaluates to 'Total / 0', which is mathematically undefined and throws a runtime Division by Zero exception.
- Part (c): To resolve this, we must introduce a conditional check (selection) to ensure division only occurs when Count is at least 1. If Count is 0, we can safely assign a default value like 0.0 to Average, avoiding the division entirely.
PastPaper.markingScheme
Part (a) [2 Marks]: - 1 mark for identifying 'Index' as the loop counter and its type as INTEGER. - 1 mark for identifying 'Total' as the accumulator and its type as INTEGER.
Part (b) [3 Marks]: - 1 mark for stating that Count remains 0 (or is never incremented). - 1 mark for stating that a division-by-zero error / runtime crash occurs. - 1 mark for identifying the line 'Average <- Total / Count' as the cause.
Part (c) [3 Marks]: - 1 mark for introducing an IF-THEN-ELSE selection block checking if Count > 0 (or Count <> 0). - 1 mark for placing the division 'Average <- Total / Count' inside the TRUE branch. - 1 mark for assigning a default value (e.g., 0.0 or -1.0) to Average inside the ELSE branch.
PastPaper.question 3 · traceTable
6 PastPaper.marks
Consider the following pseudocode algorithm which processes a 1D array of integers:
```pseudocode PROCEDURE Analyze(Arr : ARRAY, n : INTEGER) DECLARE i, count, temp : INTEGER count <- 0 temp <- Arr[1] i <- 1 WHILE i <= n DO IF Arr[i] > temp THEN temp <- Arr[i] count <- 1 ELSE IF Arr[i] = temp THEN count <- count + 1 ENDIF ENDIF i <- i + 1 ENDWHILE OUTPUT temp, count ENDPROCEDURE ```
The 1D array `Data` contains the following elements:
Trace the execution of `Analyze(Data, 6)` by completing the trace table below. Note that values should only be recorded when they are updated.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Let's trace the procedure call step by step:
1. **Initialization**: - `count` is initialized to `0`. - `temp` is initialized to `Arr[1]` which is `12`. - `i` is initialized to `1`.
2. **Loop Iterations**: - **Iteration 1 (`i = 1`)**: - `Arr[1]` is `12`. Is `12 > 12`? No. - Is `Arr[1] = temp`? Yes (`12 = 12`). - `count` becomes `1`. - `i` is incremented to `2`. - **Iteration 2 (`i = 2`)**: - `Arr[2]` is `15`. Is `15 > 12`? Yes. - `temp` becomes `15`. - `count` is reset to `1`. - `i` is incremented to `3`. - **Iteration 3 (`i = 3`)**: - `Arr[3]` is `8`. Is `8 > 15`? No. - Is `8 = 15`? No. - `i` is incremented to `4`. - **Iteration 4 (`i = 4`)**: - `Arr[4]` is `15`. Is `15 > 15`? No. - Is `15 = 15`? Yes. - `count` becomes `2`. - `i` is incremented to `5`. - **Iteration 5 (`i = 5`)**: - `Arr[5]` is `20`. Is `20 > 15`? Yes. - `temp` becomes `20`. - `count` is reset to `1`. - `i` is incremented to `6`. - **Iteration 6 (`i = 6`)**: - `Arr[6]` is `15`. Is `15 > 20`? No. - Is `15 = 20`? No. - `i` is incremented to `7`.
3. **Loop Termination**: - `i <= 6` evaluates to False (since `i` is `7`). - Output statement outputs the values of `temp` (`20`) and `count` (`1`).
PastPaper.markingScheme
Marks are awarded as follows (Max 6): - **1 mark** for correct initial values of `temp` (12), `count` (0), and `i` (1). - **1 mark** for correct updates at `i = 1` (`count` becomes 1, `i` becomes 2). - **1 mark** for correct updates at `i = 2` (`temp` becomes 15, `count` remains/becomes 1, `i` becomes 3). - **1 mark** for correct updates at `i = 3` and `i = 4` (`i` becomes 4, then `count` becomes 2, `i` becomes 5). - **1 mark** for correct updates at `i = 5` and `i = 6` (`temp` becomes 20, `count` becomes 1, `i` ends at 7). - **1 mark** for correct final `OUTPUT` ("20, 1").
PastPaper.question 4 · traceTable
6 PastPaper.marks
Consider the following pseudocode function which processes an input string:
```pseudocode FUNCTION ProcessString(S : STRING) RETURNS STRING DECLARE length, i : INTEGER DECLARE result, char : STRING result <- "" length <- LENGTH(S) i <- 1 WHILE i <= length DO char <- MID(S, i, 1) IF i MOD 2 = 1 THEN result <- CONCAT(result, UCASE(char)) ELSE IF char <> "a" AND char <> "e" AND char <> "o" THEN result <- CONCAT(result, char) ENDIF ENDIF i <- i + 1 ENDWHILE RETURN result ENDFUNCTION ```
Complete the trace table below for the function call `ProcessString("cabbage")`.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Let's trace the execution of `ProcessString("cabbage")` step by step:
- The input string `S` is `"cabbage"`. Its length is `7`. - `result` is initialized to `""`, `i` to `1`. - **Iteration 1 (`i = 1`)**: - `char` is `"c"`. - `i MOD 2 = 1` is True (`1 MOD 2 = 1`). - `result` becomes `CONCAT("", UCASE("c"))` = `"C"`. - `i` increments to `2`. - **Iteration 2 (`i = 2`)**: - `char` is `"a"`. - `i MOD 2 = 1` is False. - Conditionally, we check `char <> "a" AND char <> "e" AND char <> "o"` which is False (since `char` is `
PastPaper.markingScheme
Marks are awarded as follows (Max 6): - **1 mark** for correct initialization of `result` and `i`. - **1 mark** for correct trace of `i = 1` and `i = 2` (`char` updates, `result` updates to `"C"` then remains `"C"`, `i` reaches 3). - **1 mark** for correct trace of `i = 3` (`char = "b"`, `result` updates to `"CB"`, `i` becomes 4). - **1 mark** for correct trace of `i = 4` (`char = "b"`, `result` updates to `"CBb"`, `i` becomes 5). - **1 mark** for correct trace of `i = 5` and `i = 6` (`char = "a"` and `"g"`, `result` updates to `"CBbA"` then `"CBbAg"`, `i` becomes 7). - **1 mark** for correct trace of `i = 7`, `i` reaching 8, and the correct returned value `"CBbAgE"`.
PastPaper.question 5 · pseudocodeAlgorithm
10 PastPaper.marks
Write pseudocode for a procedure `FindLongestRun(Data : ARRAY[1:50] OF INTEGER, BYREF StartIndex : INTEGER, BYREF RunLength : INTEGER)`.
The procedure must search the 1D array `Data` to find the longest sequence of consecutive identical numbers. The procedure must return the starting index of this sequence and its length through the reference parameters `StartIndex` and `RunLength` respectively.
If there are multiple sequences with the same maximum length, the first one encountered must be returned.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
The solution requires tracking the start index and length of both the currently processed run and the maximum run found so far. As we iterate through the array from the second element, we compare each element to its predecessor. If they match, the current run length is incremented. If they do not match, the current run is finished; we compare its length to the maximum run length found so far, updating the maximums if the current run is strictly longer. Crucially, a final check must occur after the loop terminates to handle cases where the longest run extends to the very last element of the array.
PastPaper.markingScheme
1 mark: Correct procedure header including correct parameter names, array type, and use of `BYREF`. 1 mark: Declaration of local variables with correct types (`INTEGER` and `BOOLEAN` if used). 1 mark: Correct initialization of run tracking variables (`CurrentStart`, `CurrentLen`, `MaxStart`, `MaxLen`). 1 mark: Loop structures that correctly iterate through the array indices from 2 to 50. 1 mark: Conditional check comparing `Data[i]` with `Data[i-1]`. 1 mark: Correctly incrementing `CurrentLen` when elements match. 1 mark: Correctly updating `MaxLen` and `MaxStart` when a longer run is concluded, and resetting `CurrentLen` and `CurrentStart`. 1 mark: Essential post-loop check to handle run ending at the final element. 1 mark: Correct assignment of findings to the reference parameters `StartIndex` and `RunLength`. 1 mark: Use of correct pseudocode keywords throughout (`PROCEDURE`, `ENDPROCEDURE`, `DECLARE`, `FOR`, `TO`, `NEXT`, `IF`, `THEN`, `ELSE`, `ENDIF`).
PastPaper.question 6 · pseudocodeAlgorithm
10 PastPaper.marks
A game uses a 2D array `Grid` of size 10 by 10 containing characters. Empty spaces are represented by '.', obstacles by '#', and treasures by 'T'. Traps are represented by 'X'.
Write pseudocode for a function `CountSafeTreasures(Grid : ARRAY[1:10, 1:10] OF CHAR) RETURNS INTEGER`. A treasure ('T') is considered safe if it is not horizontally or vertically adjacent to any trap ('X'). The function must count and return the total number of safe treasures in the grid. Ensure that your algorithm handles boundary elements correctly without causing out-of-bounds index errors.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
The function uses nested loops to traverse every coordinate in the 10x10 grid. When it encounters a character 'T', it temporarily assumes the treasure is safe by setting a boolean flag `Safe` to `TRUE`. It then performs up to four boundary-checked adjacent lookups (Up, Down, Left, Right). If any trap 'X' is detected adjacent to the treasure, `Safe` is updated to `FALSE`. If the treasure remains safe after all possible checks, the total count is incremented. Finally, the function returns this count.
PastPaper.markingScheme
1 mark: Correct function header and `RETURNS INTEGER` syntax. 1 mark: Declaring all required local variables with appropriate types. 1 mark: Correctly nesting loops to iterate from 1 to 10 for both row and column. 1 mark: Correct initialization of counter to 0. 1 mark: Checking if the current grid cell equals 'T'. 1 mark: Implementing safe bounds checks before accessing row-1 and row+1. 1 mark: Implementing safe bounds checks before accessing col-1 and col+1. 1 mark: Checking adjacent cells for 'X' and updating safety flag accordingly. 1 mark: Incrementing counter only when safety flag remains true. 1 mark: Correctly returning the calculated count at the end of the function and closing structures.
PastPaper.question 7 · pseudocodeAlgorithm
10 PastPaper.marks
A text file named `Students.txt` contains student records, where each line represents a single student in the format: `,,` (for example: `ST1043,Alice Smith,84`).
Write pseudocode for a procedure `CalculateClassAverage()`. The procedure must read all records from the file, extract the integer score for each student, and calculate the overall average score. It must also count how many students scored below 50. Finally, the procedure must output the calculated average score and the count of students scoring below 50. If the file contains no records, an appropriate message should be displayed.
You may assume the existence of a built-in function `TONUM(StringVal : STRING) RETURNS INTEGER` to convert a string of digits to an integer.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
The procedure opens `Students.txt` in read mode. It enters a loop that continues until the end of the file is reached. For each line, the program parses the string character-by-character to locate commas. Since the format is `,,`, the score always follows the second comma. Once the second comma is detected, any subsequent characters are accumulated into a `ScoreStr` variable. This string is then converted to an integer using `TONUM(ScoreStr)`, added to `TotalScore`, and evaluated to see if it is less than 50. After processing all lines, the file is closed. The average is calculated (guarding against division-by-zero if the file was empty), and the results are output.
PastPaper.markingScheme
1 mark: Correctly opening `Students.txt` in READ mode and closing it after the loop. 1 mark: Using a correct loop structure `WHILE NOT EOF("Students.txt")` and reading a line inside the loop. 1 mark: Initializing counters and accumulators (`TotalScore`, `StudentCount`, `Below50Count`) to 0. 1 mark: Correctly counting the commas to isolate the characters representing the score. 1 mark: Accumulating/extracting the score characters into a separate string correctly. 1 mark: Using `TONUM` to convert the score string to an integer. 1 mark: Accumulating the integer score to `TotalScore` and incrementing `StudentCount`. 1 mark: Comparing the integer score to 50 and incrementing `Below50Count` if necessary. 1 mark: Calculating the average score safely by checking if `StudentCount > 0`. 1 mark: Displaying output messages for both the successful state and the empty file scenario.
A real number is stored in a 16-bit floating-point representation, with: - a 10-bit mantissa in two's complement format. - a 6-bit exponent in two's complement format.
(a) Show the normalised floating-point representation of the denary value \(-13.375\) in this 16-bit format. Show your working. [5 marks]
(b) Describe how the range and precision of this representation are affected if the format is changed to a 12-bit mantissa and a 4-bit exponent. [3 marks]
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) 1. Convert the magnitude of the number to binary: \(13 = 1101_2\) \(0.375 = 0.25 + 0.125 = 2^{-2} + 2^{-3} = 0.011_2\) So, \(13.375 = 1101.011_2\).
2. Pad the positive number to at least 10 bits before converting to negative: \(01101.01100_2\)
3. Convert to two's complement for the negative value: - Invert all bits: \(10010.10011_2\) - Add 1: \(10010.10100_2\)
4. Normalise the negative binary number (it must start with \(1.0\)): Shift the binary point 4 places to the left: \(1.001010100_2 \times 2^4\).
5. Extract the 10-bit mantissa: `1001010100`.
6. Convert the exponent (\(+4\)) to a 6-bit two's complement binary integer: \(4 = 000100_2\).
(b) - Precision is increased because more bits (12 instead of 10) are allocated to the mantissa, which allows for representation of smaller fractional increments. - Range is decreased because fewer bits (4 instead of 6) are allocated to the exponent, so the largest and smallest scale factors that can be applied are significantly smaller (maximum exponent reduces from \(31\) to \(7\)).
PastPaper.markingScheme
(a) [Total: 5 marks] - 1 mark for converting absolute value to binary: \(1101.011_2\) - 1 mark for correct two's complement conversion of value: \(10010.10100_2\) - 1 mark for correct normalisation shift of 4 places to the left. - 1 mark for correct 10-bit mantissa: `1001010100` - 1 mark for correct 6-bit exponent: `000100`
(b) [Total: 3 marks] - 1 mark for stating that precision increases because of a longer mantissa. - 1 mark for stating that range decreases because of a shorter exponent. - 1 mark for providing a quantitative explanation of the change in exponent range (e.g. 4-bit exponent limits the scale factor to between \(-8\) and \(+7\), whereas a 6-bit exponent allowed up to \(+31\)).
Two floating-point numbers are represented in a system using: - an 8-bit normalised mantissa in two's complement format. - a 4-bit exponent in two's complement format.
The two numbers are: - Number X: Mantissa = `0.1101000`, Exponent = `0011` - Number Y: Mantissa = `0.1010000`, Exponent = `0010`
Show the steps to perform binary addition of Number X and Number Y. State the final sum in the same normalised floating-point format. [8 marks]
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Step 1: Identify the exponents of both numbers. - Exponent of X is `0011` (denary \(+3\)). - Exponent of Y is `0010` (denary \(+2\)).
Step 2: Align the exponents. The smaller exponent (Y) must be adjusted to match the larger exponent (X). - To change Y's exponent from \(2\) to \(3\), shift its mantissa 1 place to the right. - Shifted Mantissa of Y = `0.0101000`
Step 3: Add the two mantissas. ``` 0.1101000 (Mantissa of X) + 0.0101000 (Shifted Mantissa of Y) ----------- 1.0010000 ```
Step 4: Analyze the result. - Both operands were positive (sign bit `0`), but the sum has a sign bit of `1`. This indicates a mantissa overflow (the result is too large to be represented with this mantissa without shifting).
Step 5: Normalise the result. - Shift the sum's mantissa 1 place to the right and insert the correct sign bit `0` at the MSB position: `0.1001000`. - To compensate for this right shift, increment the exponent by 1. - New exponent = \(3 + 1 = 4\), which is represented in 4-bit binary as `0100`.
Final representation: - Mantissa: `0.1001000` - Exponent: `0100`
PastPaper.markingScheme
- 1 mark: Identify that exponents are different (3 and 2). - 1 mark: Correctly choose to scale the smaller number (Y) to exponent 3. - 1 mark: Shift Y's mantissa to the right by 1 place to obtain `0.0101000`. - 1 mark: Set up the correct binary addition of mantissas: `0.1101000` + `0.0101000`. - 1 mark: Calculate the correct sum of the mantissas: `1.0010000`. - 1 mark: Identify that a mantissa overflow has occurred (adding two positive numbers resulted in a leading 1). - 1 mark: Correctly normalise the result by shifting the mantissa right to `0.1001000`. - 1 mark: Correctly increment the exponent to 4 (`0100`).
A logic circuit is defined by the following Boolean expression: \(Z = (\bar{A} \cdot B \cdot \bar{C}) + (\bar{A} \cdot B \cdot C) + (A \cdot \bar{B} \cdot C) + (A \cdot B \cdot C)\)
(a) Draw a Karnaugh Map (K-map) for the expression \(Z\) and loop the groups to simplify the expression. [4 marks]
(b) Write the simplified Boolean expression for \(Z\) derived from your K-map. Show how the same simplified expression can be obtained algebraically using Boolean algebra laws, stating the name of each law used. [4 marks]
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) Draw a K-map with variable \(A\) on the row and variables \(B\) and \(C\) on the columns:
Looping the 1s: - Loop 1 (Horizontal in row A=0): Covers cell \((0, 11)\) and \((0, 10)\). This simplifies to: \(\bar{A} \cdot B\). - Loop 2 (Horizontal in row A=1): Covers cell \((1, 01)\) and \((1, 11)\). This simplifies to: \(A \cdot C\).
(Note: The vertical loop covering \((0,11)\) and \((1,11)\) which yields \(B \cdot C\) is redundant as its 1s are already covered by the other two loops).
(b) Simplified expression: \(Z = (\bar{A} \cdot B) + (A \cdot C)\)
Algebraic Simplification: 1. Group the first two terms and the last two terms: \(Z = (\bar{A} \cdot B \cdot \bar{C} + \bar{A} \cdot B \cdot C) + (A \cdot \bar{B} \cdot C + A \cdot B \cdot C)\)
2. Factorise using the Distributive Law: \(Z = (\bar{A} \cdot B) \cdot (\bar{C} + C) + (A \cdot C) \cdot (\bar{B} + B)\)
3. Simplify using the Complement Law (\(X + \bar{X} = 1\)): \(Z = (\bar{A} \cdot B) \cdot 1 + (A \cdot C) \cdot 1\)
4. Simplify using the Identity Law (\(X \cdot 1 = X\)): \(Z = (\bar{A} \cdot B) + (A \cdot C)\)
PastPaper.markingScheme
(a) [Total: 4 marks] - 1 mark for correct K-map layout with correct gray code column headings (`00`, `01`, `11`, `10`). - 1 mark for entering 1s in the correct positions (row 0: cols 11, 10; row 1: cols 01, 11). - 1 mark for looping the group of two horizontal 1s in row 0 (yielding \(\bar{A} \cdot B\)). - 1 mark for looping the group of two horizontal 1s in row 1 (yielding \(A \cdot C\)) and not including redundant loops.
(b) [Total: 4 marks] - 1 mark for correct simplified expression: \(Z = (\bar{A} \cdot B) + (A \cdot C)\) (accept alternative notations like `~A.B + A.C`). - 1 mark for applying Distributive law to factorise terms. - 1 mark for using Complement law to reduce terms (e.g., \(\bar{C} + C = 1\)). - 1 mark for using Identity law to produce the final simplified expression.
PastPaper.question 4 · logicSimplification
6 PastPaper.marks
Simplify the following Boolean expression using Boolean algebra laws. Show all your working and state the laws used at each stage.
\( X = \overline{A \cdot B + \overline{A \cdot C}} + A \cdot B \)
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Step 1: Apply De Morgan's Law to split the outer complement of the first term: \( \overline{A \cdot B + \overline{A \cdot C}} = \overline{A \cdot B} \cdot \overline{\overline{A \cdot C}} \)
Step 2: Simplify the double negation: \( \overline{\overline{A \cdot C}} = A \cdot C \) This gives: \( \overline{A \cdot B} \cdot (A \cdot C) \)
Step 3: Apply De Morgan's Law to \( \overline{A \cdot B} \): \( (\overline{A} + \overline{B}) \cdot (A \cdot C) \)
Step 4: Distribute \( A \cdot C \) over the terms in the bracket: \( (\overline{A} \cdot A \cdot C) + (\overline{B} \cdot A \cdot C) \)
Step 5: Use Complement Law (\( \overline{A} \cdot A = 0 \)): \( 0 \cdot C + A \cdot \overline{B} \cdot C = A \cdot \overline{B} \cdot C \)
Step 6: Combine with the remaining term \( A \cdot B \): \( X = A \cdot \overline{B} \cdot C + A \cdot B \)
Step 7: Factor out \( A \) (Distributive Law): \( X = A \cdot (\overline{B} \cdot C + B) \)
Step 8: Simplify the expression inside the parentheses using the Distributive Law: \( \overline{B} \cdot C + B = (B + \overline{B}) \cdot (B + C) = 1 \cdot (B + C) = B + C \)
Step 9: Expand to get final expression: \( X = A \cdot B + A \cdot C \)
PastPaper.markingScheme
- 1 mark: Apply De Morgan's Law to split the outer complement of the first term. - 1 mark: Remove double negation and apply De Morgan's to get \( (\overline{A} + \overline{B}) \cdot A \cdot C \). - 1 mark: Distribute and apply Complement law to resolve \( \overline{A} \cdot A = 0 \), yielding \( A \cdot \overline{B} \cdot C \). - 1 mark: Reconstruct the full expression with the second term: \( A \cdot \overline{B} \cdot C + A \cdot B \). - 1 mark: Factor out \( A \) to get \( A(\overline{B} \cdot C + B) \). - 1 mark: Use Distributive law to simplify the bracket to \( B + C \) and reach final answer: \( A \cdot B + A \cdot C \) (or \( A(B + C) \)).
PastPaper.question 5 · logicSimplification
6 PastPaper.marks
Simplify the following Boolean expression using Boolean algebra laws. Show all your working and state the laws used at each stage.
\( Y = \overline{(P + Q) \cdot (\overline{P} + \overline{Q})} + P \cdot \overline{Q} \)
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
Step 1: Apply De Morgan's Law to split the outer negation of the product: \( \overline{(P + Q) \cdot (\overline{P} + \overline{Q})} = \overline{P + Q} + \overline{\overline{P} + \overline{Q}} \)
Step 2: Apply De Morgan's Law and Double Negation to both terms: - \( \overline{P + Q} = \overline{P} \cdot \overline{Q} \) - \( \overline{\overline{P} + \overline{Q}} = \overline{\overline{P}} \cdot \overline{\overline{Q}} = P \cdot Q \) This yields: \( \overline{P} \cdot \overline{Q} + P \cdot Q \)
Step 3: Combine with the remaining term \( P \cdot \overline{Q} \): \( Y = \overline{P} \cdot \overline{Q} + P \cdot Q + P \cdot \overline{Q} \)
Step 4: Group terms with the common factor \( \overline{Q} \): \( Y = \overline{Q} \cdot (\overline{P} + P) + P \cdot Q \)
Step 5: Apply the Complement Law (\( \overline{P} + P = 1 \)): \( Y = \overline{Q} \cdot 1 + P \cdot Q = \overline{Q} + P \cdot Q \)
Step 6: Simplify using the Distributive Law: \( \overline{Q} + P \cdot Q = (\overline{Q} + P) \cdot (\overline{Q} + Q) = (\overline{Q} + P) \cdot 1 = P + \overline{Q} \)
PastPaper.markingScheme
- 1 mark: Correct application of De Morgan's Law to split the outer product. - 1 mark: Correct simplification of individual terms to reach \( \overline{P} \cdot \overline{Q} + P \cdot Q \). - 1 mark: Reconstruct complete expression: \( \overline{P} \cdot \overline{Q} + P \cdot Q + P \cdot \overline{Q} \). - 1 mark: Group terms and factor out \( \overline{Q} \) to get \( \overline{Q}(\overline{P} + P) + P \cdot Q \). - 1 mark: Apply Complement law to simplify expression to \( \overline{Q} + P \cdot Q \). - 1 mark: Apply Distributive law to reach final correct expression: \( P + \overline{Q} \) (or \( \overline{Q} + P \)).
PastPaper.question 6 · advancedTheoryShortAnswer
10 PastPaper.marks
A real number is stored using floating-point representation with a 10-bit mantissa and a 6-bit exponent, both in two's complement format. (a) Convert the denary value \(-11.625\) into this floating-point format. Show all your working. (b) Calculate the smallest positive non-zero value that can be represented as a normalized floating-point number in this format. Express your answer as a power of 2 and state the binary representation of both the mantissa and exponent. (c) Explain what is meant by underflow in floating-point operations.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) 1. Convert positive 11.625 to binary: 11 = 1011, 0.625 = 0.5 + 0.125 = 0.101. So, 11.625 is 1011.101 in binary. 2. Normalize the positive value: shift the binary point 4 places to the left to get 0.1011101 * 2^4. 3. Pad the mantissa to 10 bits: 0.101110100. 4. Convert the mantissa to two's complement for the negative representation: invert the bits to get 1.010001011, then add 1 to get 1.010001100. 5. Convert the exponent (+4) to a 6-bit two's complement number: 000100. (b) The smallest positive normalized mantissa is 0.100000000, which has a value of 0.5 (or 2^(-1)). The minimum possible exponent in 6-bit two's complement is -32, which is represented as 100000. The smallest positive non-zero value is therefore 0.5 * 2^(-32) = 2^(-33). (c) Underflow occurs when the result of a floating-point calculation is a non-zero number that is too small (closer to zero than the smallest representable value) to be stored in the available mantissa and exponent bits.
PastPaper.markingScheme
(a) [5 Marks] - 1 mark: finding binary of 11.625 is 1011.101. - 1 mark: normalizing positive mantissa to 0.101110100. - 1 mark: taking two's complement of the mantissa to get 1.010001100. - 1 mark: identifying exponent is +4. - 1 mark: converting exponent to 6-bit binary 000100. (b) [3 Marks] - 1 mark: identifying smallest positive normalized mantissa is 0.100000000. - 1 mark: identifying minimum exponent as -32 (or 100000 in binary). - 1 mark: calculating final value of 2^(-33). (c) [2 Marks] - 1 mark: explaining underflow as a result too small to represent. - 1 mark: specifying it occurs when a positive value is closer to zero than the system's absolute minimum limit.
PastPaper.question 7 · advancedTheoryShortAnswer
10 PastPaper.marks
A Turing machine is designed to locate the first occurrence of the sequence 'AB' on a tape containing symbols 'A', 'B', and '_' (blank space), swap them to 'BA', and then halt. The machine has states S0 (start state), S1, S2, and Shalt. (a) The transition rules are partially defined as follows: (S0, A) -> (A, R, S1), (S0, B) -> (B, R, S0), (S1, A) -> (A, R, S1). Provide the three missing transition rules to complete the logic: (i) State S0 when reading '_', (ii) State S1 when reading 'B', (iii) State S2 when reading 'A'. (b) Trace the execution of this Turing machine starting in state S0 with tape contents 'AAB_' and the read head at the leftmost 'A' (index 0). List the state, tape contents, and read head position at each step. (c) Explain the difference between a halting state and an infinite loop in a Turing machine.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a)(i) (S0, _) -> (_, L, Shalt) - If no 'A' has been found and we reach blank, we halt. (ii) (S1, B) -> (A, L, S2) - When we have seen 'A' and now see 'B', we write 'A' here, move left to the previous cell and enter S2. (iii) (S2, A) -> (B, R, Shalt) - In S2, we read the previous 'A', write 'B' over it, move right and halt. (b) Step 1: State S0, tape 'AAB_', head at index 0 ('A'). Transitions to S1, tape remains 'AAB_', head moves to index 1 ('A'). Step 2: State S1, tape 'AAB_', head at index 1 ('A'). Transitions to S1, tape remains 'AAB_', head moves to index 2 ('B'). Step 3: State S1, tape 'AAB_', head at index 2 ('B'). Transitions to S2, tape becomes 'AAA_', head moves to index 1 ('A'). Step 4: State S2, tape 'AAA_', head at index 1 ('A'). Transitions to Shalt, tape becomes 'ABA_', head moves to index 2 ('A'). Machine halts. (c) A halting state is a designated terminal state from which no further moves are defined, allowing the machine to stop execution cleanly once a task is finished. An infinite loop occurs when the machine continuously transitions between states without ever reaching a halting state, moving along the tape or rewriting cells indefinitely.
PastPaper.markingScheme
(a) [3 Marks] - 1 mark: correct rule for S0 on '_': (S0, _) -> (_, L, Shalt). - 1 mark: correct rule for S1 on 'B': (S1, B) -> (A, L, S2). - 1 mark: correct rule for S2 on 'A': (S2, A) -> (B, R, Shalt). (b) [5 Marks] - 1 mark: Step 1 correct (S1, 'AAB_', head at 1). - 1 mark: Step 2 correct (S1, 'AAB_', head at 2). - 1 mark: Step 3 correct (S2, 'AAA_', head at 1). - 1 mark: Step 4 correct (Shalt, 'ABA_', head at 2). - 1 mark: Correctly showing final tape as 'ABA_'. (c) [2 Marks] - 1 mark: Defining halting state as a formal stopping point. - 1 mark: Defining infinite loop as a cyclical non-terminating state transition path.
PastPaper.question 8 · advancedTheoryShortAnswer
10 PastPaper.marks
A software publisher distributes secure system updates over the internet. To ensure the authenticity and integrity of the software packages, the company signs them with a digital signature. (a) Describe how the company uses asymmetric encryption and hashing to generate the digital signature. (b) Explain how a client machine verifies this digital signature to ensure the software update is genuine and has not been altered. (c) Explain why the publisher does not encrypt the entire software update file using their private key to secure it.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) 1. The software publisher runs the update file through a cryptographic hash function (such as SHA-256) to produce a unique, fixed-size hash value (or message digest). 2. The publisher then encrypts this hash value using their private key. The encrypted hash is the digital signature, which is appended to the software update file. (b) 1. The client machine receives the update file and the digital signature. 2. The client decrypts the digital signature using the publisher's public key to recover the original hash value. 3. The client applies the same cryptographic hash function to the received update file to calculate a new hash value. 4. The client compares the decrypted hash with the calculated hash; if they match, the file is authentic and has not been altered. (c) Asymmetric encryption is computationally complex and slow compared to symmetric encryption or hashing. Because software update files are typically large, encrypting the entire file would be highly inefficient and resource-intensive. Hashing creates a small, fixed-size representation that is extremely fast to encrypt and decrypt.
PastPaper.markingScheme
(a) [4 Marks] - 1 mark: applying a cryptographic hash function to the software update file. - 1 mark: generating a unique, fixed-size hash value. - 1 mark: encrypting the hash value. - 1 mark: using the publisher's private key for encryption. (b) [4 Marks] - 1 mark: decrypting the digital signature using the publisher's public key. - 1 mark: retrieving the original hash value. - 1 mark: hashing the received file with the same algorithm. - 1 mark: comparing the two hashes to verify integrity and origin. (c) [2 Marks] - 1 mark: stating that asymmetric encryption is slow/computationally expensive. - 1 mark: explaining that encrypting a small hash is far more efficient than encrypting a large file.
PastPaper.question 9 · advancedTheoryShortAnswer
10 PastPaper.marks
A logic programming system contains the following database of facts and rules:
(a) Write a recursive rule, requires(X, Y), that is true if course Y directly or indirectly requires course X as a prerequisite. (b) Trace the execution of the query: ?- requires(cs101, cs201). showing all evaluation steps, subgoals, and instantiations. (c) Distinguish between a 'fact' and a 'rule' in Prolog. (d) State the purpose of the cut (!) operator.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
(a) The recursive logic has a base case and a recursive case: requires(X, Y) :- prereq(X, Y). requires(X, Y) :- prereq(X, Z), requires(Z, Y).
(b) Execution Trace: 1. Prolog first tries the base case: requires(cs101, cs201) :- prereq(cs101, cs201). It checks the database and fails because there is no such fact. 2. Prolog backtracks and tries the recursive case: requires(cs101, cs201) :- prereq(cs101, Z), requires(Z, cs201). 3. It searches the database for prereq(cs101, Z) and matches prereq(cs101, cs102), instantiating Z = cs102. 4. This sets up the subgoal: requires(cs102, cs201). 5. Prolog evaluates requires(cs102, cs201) by trying the base case first: prereq(cs102, cs201). This matches the database fact prereq(cs102, cs201), so the subgoal succeeds. 6. The parent goal requires(cs101, cs201) succeeds.
(c) A fact is an absolute assertion in the database that is unconditionally true (e.g., course(cs101).). A rule is a conditional statement (using ':-') that is only true if its constituent subgoals on the right-hand side can be satisfied.
(d) The cut operator (!) prevents backtracking past the point where it is placed in a rule, committing the system to any choices made up to that point.
PastPaper.markingScheme
(a) [3 Marks] - 1 mark: correct base case: requires(X, Y) :- prereq(X, Y). - 2 marks: correct recursive case: requires(X, Y) :- prereq(X, Z), requires(Z, Y). (Accept alternative recursive formulations that are logically equivalent). (b) [4 Marks] - 1 mark: explaining that the base case fails initially. - 1 mark: explaining recursive case is triggered and Z is instantiated to cs102. - 1 mark: setting up the subgoal requires(cs102, cs201). - 1 mark: showing subgoal matches the base case fact and succeeds. (c) [2 Marks] - 1 mark: defining a fact as unconditionally true. - 1 mark: defining a rule as conditionally true based on subgoals. (d) [1 Mark] - 1 mark: stating that the cut operator prevents backtracking (or increases efficiency by pruning the search tree).
Paper 4 (Practical)
Use a high-level language (Python/Java/VB) to implement the tasks. Include screenshots of testing.
3 PastPaper.question · 75 PastPaper.marks
PastPaper.question 1 · fileHandlingAndArrays
27 PastPaper.marks
An international gaming tournament records player high scores in a text file named "Scores.txt". There are exactly 10 players. Each line of the text file contains a unique 4-character Player ID and an integer score, separated by a comma.
Example text file contents: PL45,3400 PL12,8900 ...
You are required to write program code to read these scores into an array of objects, sort them in descending order of scores, and display the sorted list.
Write program code to perform the following tasks:
1. Define a class "ScoreRecord" with: - private attributes "PlayerID" (String) and "Score" (Integer) - a constructor that takes two parameters to initialize these attributes - getter methods "GetPlayerID()" and "GetScore()". Declare a global 1D array named "ScoreList" of size 10 to store objects of type "ScoreRecord". [6 Marks]
2. Write a function "ReadData()" that: - reads the data from the text file "Scores.txt" - populates the global array "ScoreList" with instances of "ScoreRecord" - handles file exceptions appropriately - returns "True" if the file is successfully read, otherwise returns "False". [7 Marks]
3. Write a procedure "BubbleSort()" that implements a bubble sort algorithm to sort the elements of the global array "ScoreList" in descending order based on the "Score" attribute. [8 Marks]
4. Write the main program structure that: - Calls "ReadData()". - If "ReadData()" returns "True", calls "BubbleSort()" and displays the sorted contents of "ScoreList" showing both the player ID and score in a formatted list. - If "ReadData()" returns "False", displays an error message "Error: File not found or read error." [6 Marks]
def ReadData(): global ScoreList try: file = open("Scores.txt", "r") index = 0 for line in file: line = line.strip() if line != "": data = line.split(",") player_id = data[0] score = int(data[1]) ScoreList[index] = ScoreRecord(player_id, score) index += 1 file.close() return True except FileNotFoundError: return False
def BubbleSort(): global ScoreList n = len(ScoreList) for i in range(n): for j in range(0, n - i - 1): if ScoreList[j] is not None and ScoreList[j+1] is not None: if ScoreList[j].GetScore() < ScoreList[j+1].GetScore(): temp = ScoreList[j] ScoreList[j] = ScoreList[j+1] ScoreList[j+1] = temp
def Main(): if ReadData(): BubbleSort() print("Sorted High Scores (Descending):") for item in ScoreList: if item is not None: print("Player ID: " + item.GetPlayerID() + ", Score: " + str(item.GetScore())) else: print("Error: File not found or read error.")
class ScoreRecord { private String playerID; private int score;
public ScoreRecord(String playerID, int score) { this.playerID = playerID; this.score = score; }
public String getPlayerID() { return playerID; } public int getScore() { return score; } }
public class Solution { private static ScoreRecord[] scoreList = new ScoreRecord[10];
public static boolean readData() { try (BufferedReader br = new BufferedReader(new FileReader("Scores.txt"))) { String line; int index = 0; while ((line = br.readLine()) != null && index < 10) { if (!line.trim().isEmpty()) { String[] data = line.split(","); scoreList[index] = new ScoreRecord(data[0], Integer.parseInt(data[1])); index++; } } return true; } catch (IOException e) { return false; } }
public static void bubbleSort() { int n = scoreList.length; for (int i = 0; i < n; i++) { for (int j = 0; j < n - i - 1; j++) { if (scoreList[j] != null && scoreList[j+1] != null) { if (scoreList[j].getScore() < scoreList[j+1].getScore()) { ScoreRecord temp = scoreList[j]; scoreList[j] = scoreList[j+1]; scoreList[j+1] = temp; } } } } }
public static void main(String[] args) { if (readData()) { bubbleSort(); System.out.println("Sorted High Scores (Descending):"); for (ScoreRecord record : scoreList) { if (record != null) { System.out.println("Player ID: " + record.getPlayerID() + ", Score: " + record.getScore()); } } } else { System.out.println("Error: File not found or read error."); } } } ```
### Expected Console Output Screenshot Simulation ```text Sorted High Scores (Descending): Player ID: PL77, Score: 9100 Player ID: PL12, Score: 8900 Player ID: PL21, Score: 7800 Player ID: PL52, Score: 6700 Player ID: PL03, Score: 5600 Player ID: PL33, Score: 4500 Player ID: PL09, Score: 4300 Player ID: PL45, Score: 3400 Player ID: PL14, Score: 2300 Player ID: PL88, Score: 1200 ```
PastPaper.markingScheme
### Task 1 (6 Marks) * **1 Mark**: Defining class `ScoreRecord` with appropriate attributes specified as private. * **1 Mark**: Constructor with parameters initializing both object attributes. * **1 Mark**: Correct syntax and implementation of getter `GetPlayerID()`. * **1 Mark**: Correct syntax and implementation of getter `GetScore()`. * **1 Mark**: Declaring a global 1D array `ScoreList` of size 10. * **1 Mark**: Initializing array elements correctly to store `ScoreRecord` objects (e.g. setting them to null or empty objects).
### Task 2 (7 Marks) * **1 Mark**: Opening file `Scores.txt` in read mode. * **1 Mark**: Reading line-by-line using a loop. * **1 Mark**: Splitting the record correctly on the comma delimiter. * **1 Mark**: Casting the parsed score into an Integer type. * **1 Mark**: Creating a new object of `ScoreRecord` class and adding it to the global array `ScoreList` using an index tracker. * **1 Mark**: Standard exception handling block (e.g., try/except or try/catch) to manage file read failures. * **1 Mark**: Returning logical `True` on success and `False` on exception/failure.
### Task 3 (8 Marks) * **1 Mark**: Implementing outer loop representing bubble sort iterations (up to length - 1). * **1 Mark**: Implementing nested inner loop iterating through the unsorted portion of the array. * **1 Mark**: Checking if array elements are not null/None before comparison to avoid null pointer reference issues. * **1 Mark**: Accessing high score values using getter methods correctly inside the sort algorithm comparison. * **1 Mark**: Correct descending comparison check (`<` or equivalent logic to push lower values to the end). * **2 Marks**: Temporary variable sequence implementing swap properly. * **1 Mark**: Correct syntax throughout without logical index-out-of-bounds error.
### Task 4 (6 Marks) * **1 Mark**: Calling `ReadData()` function in main execution block. * **1 Mark**: Correct conditional execution based on boolean return of `ReadData()`. * **1 Mark**: Calling `BubbleSort()` when file is read successfully. * **1 Mark**: Standard loop traversing sorted `ScoreList` to output values. * **1 Mark**: Outputting values clearly using getter methods (PlayerID and Score). * **1 Mark**: Outputting error message correctly if the file read returns `False`.
PastPaper.question 2 · recursiveAlgorithms
17 PastPaper.marks
An algorithm is required to process two integers recursively.
(a) Write program code to implement the recursive function `AnalyzePattern(Value1, Value2)`. The function behaves as follows: - It takes two integer parameters, `Value1` and `Value2`. - If `Value1` is less than or equal to 0, or `Value2` is less than or equal to 0, the function returns 0. - If `Value1` is equal to `Value2`, it returns the sum of `Value1` and the result of a recursive call to `AnalyzePattern` with `Value1 - 1` and `Value2 - 1`. - If `Value1` is greater than `Value2`, it returns the sum of `Value1` and the result of a recursive call to `AnalyzePattern` with `Value1 - 2` and `Value2 - 1`. - If `Value1` is less than `Value2`, it returns the sum of `Value2` and the result of a recursive call to `AnalyzePattern` with `Value1 - 1` and `Value2 - 2`. [6 marks]
(b) Write program code for a main program that: - Calls `AnalyzePattern(8, 5)` and outputs the returned value. - Calls `AnalyzePattern(3, 7)` and outputs the returned value. Include screenshots of the output. [5 marks]
(c) Write program code for an iterative function `IteratePattern(Value1, Value2)` that performs the same process and returns the same values without using recursion. Amend your main program to call `IteratePattern(8, 5)` and `IteratePattern(3, 7)` to verify the output. Include screenshots of the updated output. [6 marks]
# Part (c) def IteratePattern(Value1, Value2): total = 0 v1 = Value1 v2 = Value2 while v1 > 0 and v2 > 0: if v1 == v2: total += v1 v1 -= 1 v2 -= 1 elif v1 > v2: total += v1 v1 -= 2 v2 -= 1 else: total += v2 v1 -= 1 v2 -= 2 return total
# Parts (b) and (c) Main Program print('Recursive calls:') print('AnalyzePattern(8, 5) =', AnalyzePattern(8, 5)) print('AnalyzePattern(3, 7) =', AnalyzePattern(3, 7))
### Part (a) [6 Marks] - **1 Mark**: Correct function header `AnalyzePattern(Value1, Value2)`. - **1 Mark**: Base case condition: checks if `Value1 <= 0` or `Value2 <= 0` and returns `0`. - **1 Mark**: Condition `Value1 == Value2` correctly calls `AnalyzePattern(Value1 - 1, Value2 - 1)` and adds `Value1`. - **1 Mark**: Condition `Value1 > Value2` correctly calls `AnalyzePattern(Value1 - 2, Value2 - 1)` and adds `Value1`. - **1 Mark**: Condition `Value1 < Value2` correctly calls `AnalyzePattern(Value1 - 1, Value2 - 2)` and adds `Value2`. - **1 Mark**: Function returns the correct computed value in all branches (correct use of recursion with return).
### Part (b) [5 Marks] - **1 Mark**: Correct syntax for main program / script entry point. - **1 Mark**: Correct call and output statement for `AnalyzePattern(8, 5)`. - **1 Mark**: Correct call and output statement for `AnalyzePattern(3, 7)`. - **2 Marks**: Screenshot demonstrating the output. Accept screenshots that show: - `AnalyzePattern(8, 5) = 21` (1 mark) - `AnalyzePattern(3, 7) = 15` (1 mark)
### Part (c) [6 Marks] - **1 Mark**: Correct function header `IteratePattern(Value1, Value2)`. - **1 Mark**: Initialisation of an accumulator variable (e.g. `total = 0`) and setting local control variables. - **1 Mark**: Correct loop structure/condition (e.g., `while v1 > 0 and v2 > 0`). - **2 Marks**: All branches updating control variables and accumulating correctly inside the loop. (1 mark for 2 correct branches, 2 marks for all 3 correct branches). - **1 Mark**: Correct screenshot illustrating iterative output matching recursive output (i.e. values 21 and 15).
PastPaper.question 3 · objectOrientedProgramming
31 PastPaper.marks
An energy-saving system needs to track the energy consumption of various home appliances. You will design an object-oriented program to model these appliances.
### Task 1 Create a base class called `Appliance` with the following private attributes: * `__Name` : string * `__PowerRating` : integer (in Watts) * `__IsOn` : boolean
Implement the following methods for the `Appliance` class: * A constructor that takes `Name` and `PowerRating` as parameters. It must initialize `__IsOn` to `False`. * Getters for all attributes: `GetName()`, `GetPowerRating()`, and `GetIsOn()`. * `TogglePower()`: a method that changes the state of `__IsOn` (from `True` to `False`, or `False` to `True`). * `GetEnergyConsumed(Hours)`: a method that takes a real/float value representing the number of active hours. If the appliance is on, it returns the energy consumed in kilowatt-hours (kWh) calculated as: \(\text{Energy (kWh)} = \frac{\text{PowerRating} \times \text{Hours}}{1000}\). If the appliance is off, it returns `0.0`.
### Task 2 Create a subclass called `SmartAppliance` that inherits from `Appliance`. In addition to the inherited attributes, it must have these private attributes: * `__EcoMode` : boolean (initialized to `False`) * `__DutyCycle` : real/float (between 0.0 and 1.0, representing the active duty cycle ratio)
Implement the following methods for the `SmartAppliance` class: * A constructor that takes `Name`, `PowerRating`, and `DutyCycle` as parameters. It must call the base class constructor and initialize `__EcoMode` to `False` and `__DutyCycle` to the parameter value. * `SetEcoMode(EcoState)`: a method that takes a boolean parameter and sets `__EcoMode` to this value. * `GetEnergyConsumed(Hours)`: an overridden method. If the appliance is on, it returns the energy consumed in kWh. If `__EcoMode` is `True`, the duty cycle is reduced to 80% of its original value (i.e. multiplied by 0.8) during the calculation. If `__EcoMode` is `False`, the original duty cycle is used. The calculation is: \(\text{Energy (kWh)} = \frac{\text{PowerRating} \times \text{Hours} \times \text{EffectiveDutyCycle}}{1000}\). If the appliance is off, it returns `0.0`.
### Task 3 Write a main program that does the following: 1. Create an array or list named `ApplianceList` containing three objects: * An `Appliance` object: name "Oven", power rating `2400` * A `SmartAppliance` object: name "Refrigerator", power rating `150`, duty cycle `0.6` * A `SmartAppliance` object: name "Heater", power rating `2000`, duty cycle `0.9` 2. Turn all three appliances ON. 3. Turn eco-mode ON for both smart appliances. 4. Write a function `CalculateTotalEnergy(ApplianceList, Hours)` that iterates through the list, calculates the energy consumed for each appliance over the given hours, and returns the total energy consumed in kWh. 5. Call the function in your main program with `Hours` set to `4.0` and output the total energy consumption with an appropriate message.
Save your code and take a screenshot of the output.
PastPaper.showAnswersPastPaper.hideAnswers
PastPaper.workedSolution
```python class Appliance: def __init__(self, name, power_rating): self.__Name = name self.__PowerRating = power_rating self.__IsOn = False
def CalculateTotalEnergy(appliance_list, hours): total_energy = 0.0 for appliance in appliance_list: total_energy += appliance.GetEnergyConsumed(hours) return total_energy
# Main Program appliance_list = [] appliance_list.append(Appliance("Oven", 2400)) appliance_list.append(SmartAppliance("Refrigerator", 150, 0.6)) appliance_list.append(SmartAppliance("Heater", 2000, 0.9))
# Turn all appliances ON for app in appliance_list: app.TogglePower()
# Turn eco-mode ON for smart appliances for app in appliance_list: if isinstance(app, SmartAppliance): app.SetEcoMode(True)
# Calculate and print total energy hours = 4.0 total = CalculateTotalEnergy(appliance_list, hours) print(f"Total energy consumed over {hours} hours: {total:.4f} kWh") ```
### Task 1 [Max 10 marks] * Private attributes (`__Name`, `__PowerRating`, `__IsOn`) correctly declared/initialized (1 mark for syntax/privacy, 1 mark for correct types) [2 marks] * Constructor sets `__Name` and `__PowerRating` from parameters and initializes `__IsOn` to `False` [2 marks] * Three getters (`GetName()`, `GetPowerRating()`, `GetIsOn()`) correctly written [2 marks] * `TogglePower()` logic switches state of `__IsOn` [2 marks] * `GetEnergyConsumed()` checks power status and calculates correct formula with division by 1000 [2 marks]
### Task 2 [Max 9 marks] * Subclass correctly inherits from base class (correct syntax) [1 mark] * Subclass private attributes (`__EcoMode`, `__DutyCycle`) declared [1 mark] * Constructor calls parent constructor with `super()` or equivalent and sets fields [2 marks] * `SetEcoMode(EcoState)` correctly updates private variable [1 mark] * Overridden `GetEnergyConsumed()` checks if power is on (using parent state getter) [1 mark] * Calculates energy consumption applying the 20% discount if `__EcoMode` is `True` [2 marks] * Returns `0.0` if appliance is off [1 mark]
### Task 3 [Max 12 marks] * Declaring the array/list containing the 3 specified objects with correct values [3 marks] * Loop or explicit calls to turn all 3 objects ON [2 marks] * Correctly identifying smart appliances and activating Eco Mode [2 marks] * Function `CalculateTotalEnergy` declared with correct parameters [1 mark] * Iterates through collection and accumulates energy via polymorphically called `GetEnergyConsumed(Hours)` [2 marks] * Calling the function with `4.0` hours and printing the correct calculated total (15.648 kWh) with message [2 marks]