Questions
Questions
The theme of this question is developing a simple parser for LOGO programming language.
LOGO controls the commands for movement and drawing of a pointer on the screen.
We consider a grid with 11 x 21 cells, where 11 is the number of rows and 21 is the number of
columns. A pointer is represented by one of the following characters:
● “^”: The pointer is pointing to the upward direction
● “>”: The pointer is pointing to the right direction
● “<”: The pointer is pointing to the left direction
● “v”: The pointer is pointing to the downward direction
We can control the movement and drawing of the pointer by the following commands:
● LEFT: Turn the direction of the pointer by 90 degrees to the left
● RIGHT: Turn the direction of the pointer by 90 degrees to the right
● PENUP: Set the status of the pointer to be leaving no trail, when it moves
● PENDOWN: Set the status of the pointer to be leaving a trail, when it moves
● FORWARD(n): Move the pointer along the direction it is pointing by n cells
● BACK(n): Move the pointer in the reverse direction it is pointing by n cells
<Command> := LEFT | RIGHT | FORWARD(<num>) | BACK(<num>) | PENUP | PENDOWN
<Exp> := <Command>; <Exp> | <Command>;
Example:
● Initial screen: (the pointer is always initially positioned with upward direction at the center
of the grid with PENUP status)
#####################
#####################
#####################
#####################
#####################
##########^##########
#####################
#####################
#####################
#####################
#####################
● Input:
PENUP; LEFT; FORWARD(10); PENDOWN; RIGHT; BACK(5);
● Output:
#####################
#####################
#####################
#####################
#####################
.####################
.####################
.####################
.####################
.####################
^####################
where an empty cell is represented by character “#”, a cell with the trail of the pointer is
represented by character “.”, and the pointer is initially with PENUP status. Note that you do not
need to consider cases where FORWARD(n) and BACK(n) can go beyond the boundary of the
grid.
Tasks:
1) [2 marks] Setup and use git within the Q2 directory for revision control and make at least
3 commits.
2) [3 marks] Write a correct Makefile for building the program with 3 targets: “make”, “make
clean”, and “make rundemo” , which will compile, delete the compiled class files and run
“Demo.java” respectively.
3) [10 Marks] Complete “next()”, “takeNext()” and “hasNext()” methods in
“Tokenizer.java” to extract an expression into tokens.
4) [10 Marks] Complete “parse()“ method in “Parser.java” to parse an input expression by
computing the final position of the pointer and marking the pointer movement on the
screen.
5) [5 Marks] Complete “trace( )” method in “Screen.java” to return a string showing the trail
of the pointer, its current position and direction.
For 2) - 5), you may only modify the required methods within Q2 directory. Do not modify
anything else.
Question 3 - Binary Search Tree [20 marks]
Your Q3 directory contains code that implements a binary search tree with a set of string keys.
The implementation has had the code for “find”, “insert”, and “printOddNodes” removed.
Consider a comparison of keys by alphabetical order. For example, “a” < “b”. “aaab” < “ab”. You
only need to consider the lower-case alphabet.
You are required to complete the implementation replacing the missing code. Your answer
must be placed in your Q3 directory.
Tasks:
You may only modify the required methods within Q3 directory. Do not modify anything else.
Question 4 - Testing [20 marks]
Your Q4 directory contains code that implements two useful utilities. A parseInt algorithm to
convert a string to an integer is implemented in MyInteger.java, and a method for replacing
multiple newline characters by a single newline character is implemented in StringUtil.java.
Tasks:
1) [10 marks] Your first task for this question is to implement a minimum number of JUnit
test cases for MyInteger.parseInt that is code complete. Write your test case(s) in
the one test() method in MyIntegerTest.java. Use assertEquals and
assertThrows to check the correctness of the implementation.
2) [10 marks] Your second task for this question is to implement a minimum number of
JUnit test cases for StringUtil.collapseNewlines that is branch complete. Write
your test case(s) in the one test( ) method in StringUtilTest.java. U se
assertEquals to check the correctness of the implementation.
Note that ALL test cases should be written in the one test() method in each of the two test
classes. Any additional test methods created elsewhere in your answer will not be marked.
2019 Semester 2 - Final Examination
(COMP2100/COMP6442)
This exam will be marked out of 100 and consists of 4 questions, carrying 55% of the total
marks of this course. Questions are of unequal value. The value of each question is shown in
square brackets. Questions that are partitioned into parts show the number of marks given to
each part within square brackets.
Students should attempt all questions. Answers must be saved into the question's directory
(Q1, Q2, Q3, Q4) using the file(s) described in the question statement. If you do use Eclipse or
Intelij then make certain that you either create projects that edit source files directly in these
directories or that you copy your solutions to the correct directories before the end of the exam.
For the programming problems, there will be no partial marks for the uncompilable source code.
Make sure your source code is at least compilable.
The multiple choice questions are available via a program in your 'Q1' directory. This program is
also used for entering your answers. To run the multiple choice program:
1. opening a Terminal,
2. from the command line change directory (cd) into the Q1 directory, and
3. run the java MultipleChoice program.
% cd ~/Desktop/Q1
% java -jar MultiChoice.jar
Your answers are automatically saved every time you click an answer. Hence once you have
completed your answers you can simply exit from the program (either by pressing the window
closing “x” or by selecting the “exit” menu item). Note that you can restart the program and
change your answers. Do not edit files in this directory. Also, you can only have one instance
of the MultiChoice program running at any time.
There are 15 questions. Each answer you get correct gains you 2 marks.
If the question statement contains an underline, that is “____________”, then the selected
answer should correctly complete the question statement. Some question statements may
contain two underlined sections, in which case the answer has two parts separated by a
comma. The first part corresponds to the first underlined section and the second part
corresponds to the second underlined section.
Question 2 - Binary Search Tree [20 marks]
Your Q2 directory contains code that implements a binary search tree with a set of integer
numbers. The implementation has had the code for “find”, “delete” , and “sumEvenNodes”
removed.
You are required to complete the implementation replacing the missing code. Your answer
must be placed in your Q2 directory.
Tasks:
1) [7 marks] Implement the “find” method. The method should return “true” if a tree
contains a key, otherwise return “false”.
2) [7 marks] Implement the “delete” method. Use successor to replace the target node if
the target node has two children.
3) [6 marks] Implement the “sumEvenNodes” method to print the sum of the nodes that have
an even number of direct children (zero is an even number).
You may create more methods if you need. Make sure that you do not move the files in Q2
directory into another directory.
Handy tips
Your Q3 directory contains code that implements two useful utilities. MyUtil.java file contains
parseDouble method to extract the first number in an input string. MyStringUtil.java file
contains isMixedCase to check whether an input string contains both uppercase and lowercase
characters.
Tasks:
1) [10 marks] Your first task for this question is to implement a minimum number of JUnit
test cases for parseDouble that is code complete. Write your test case(s) in test()
method in MyUtilTest.java. U se assertEquals to check the correctness of the
implementation. All test cases should pass the JUnit test to get the full marks.
2) [10 marks] Your second task for this question is to implement a minimum number of
JUnit test cases for isMixedCase that is branch complete. Write your test case(s) in
test() method in MyStringUtilTest.java. Use assertEquals to check the
correctness of the implementation. All test cases should pass the JUnit test to get the
full marks.
Handy tips
Code complete: with a code complete test, all statements need to be executed at least once
during the test.
Branch complete: with a branch complete test, all possible branch condition statements
need to be executed during the test. Branch complete is different from path complete, which
needs to take into account all possible execution paths of a program.
Question 4 - Tokenizer, Parser [30 marks]
The theme of this question is developing a simple parser for LOGO programming language.
LOGO controls the commands for movement and drawing of a pointer on the screen.
Assume that we have a grid with 11 x 21 cells, where 11 is the number of rows and 21 is the
number of columns. A pointer is represented by one of the following characters:
● “^”: The pointer is facing the NORTH direction
irection
● “>”: The pointer is facing the EAST d
● “<”: The pointer is facing the WEST d irection
● “v”: The pointer is facing the SOUTH direction
We can control the movement and drawing of the pointer by the following commands:
● LEFT: Turn the direction of the pointer by 90 degrees to the left
● RIGHT: Turn the direction of the pointer by 90 degrees to the right
● PENUP: Set the status of the pointer to be leaving no trail, when it moves
● PENDOWN: Set the status of the pointer to be leaving a trail, when it moves
● FORWARD(n) : Move the pointer along the direction it is pointing by n cells
● BACK(n) : Move the pointer in the reverse direction it is pointing by n cells
● FORWARD_TO_END: Move the pointer along the direction until it reaches the boundary
of the grid
● BACK_TO_END: Move the pointer in the reverse direction until it reaches the boundary
of the grid
<Command> := LEFT | RIGHT | PENUP | PENDOWN | FORWARD(<num>) | BACK(<num>)
| FORWARD_TO_END | BACK_TO_END
<Exp> := <Command>; <Exp> | <Command>;
● Input:
PENUP; LEFT; FORWARD(10); PENDOWN; RIGHT; BACK(3);
● Output:
#####################
#####################
#####################
#####################
#####################
.####################
.####################
.####################
^####################
#####################
#####################
● Input:
PENDOWN; BACK_TO_END;
● Output:
##########v##########
##########.##########
##########.##########
##########.##########
##########.##########
##########.##########
#####################
#####################
#####################
#####################
#####################
where an empty cell is represented by character “#”, a cell with the trail of the pointer is
represented by character “.”, and the pointer is initially with PENUP status. Note that you do not
need to consider cases where FORWARD(n) and BACK(n) can go beyond the boundary of the
grid.
Please check the expected results of these methods from the JUnit test files:
TokenizerTest.java, ParserTest.java, ScreenTest.java.
For 1) - 3), you should modify the required methods within Q4 directory. You can make any
additional method if you need while completing the tasks. Make sure that you do not move the
files in Q4 directory into another directory.
Q1 - Design Pattern & Software Testing &
Persistent Data (20 marks)
One day, your supervisor assigns to you a game development task, where a character can be controlled by external
keyboard instructions.
The character has five states, where each state has only one unique instance:
StandState
LieProneState
RunState
CrawlState
ShootState
Key.UP
Key.DOWN
Key.RIGHT
Key.LEFT
Key.L
Key.S
Key.RESET
You are expected to apply the state and singleton design patterns based on the given state graph Graph.pdf.
1) You are expected to create all the state classes from scratch to pass the given test cases in
StateTest.java class, where a getInstance() method should be defined to obtain the singleton
instance of each state. Note that any state will be reset to the default StandState on Key.RESET.
2) You are required to develop robust code, which ensures that the passed-in arguments are valid.
You are expected to complete the check() method in the State interface and also create test cases
in the following methods of the ExceptionTest.java class for the exception testing:
3) You are expected to complete the read() and write() methods in the XMLProcessor.java. read() aims to read the keys
and events from the xml file. write() aims to write the keys and events to the xml file in the given order. You are required to
comply with the XML format in the given example.xml file. Ensure that the example XML file is placed in the right directory.
Please try your best to return a value for the required methods, e.g. 0 or null, to make
sure your solutions do compile if you have trouble in providing the solutions. Otherwise,
you may be subject to a mark loss due to compile errors.
State.java
StandState.java
LieProneState.java
RunState.java
CrawlState.java
ShootState.java
ExceptionTest.java
XMLProcessor.java
IMPORTANT NOTES:
Please do not add any packages at the head of any of the above uploaded files. Otherwise, your code may fail to
be compiled by the auto-marker and you may lose marks.
You are allowed to create helper methods in the required java classes. Aside from creating those helper methods,
you are only allowed to implement your code in the designated area between "YOUR CODE STARTS HERE" and
"YOUR CODE ENDS HERE".
Some test cases are provided to assist your understanding, but passing them does not guarantee you will get full
marks. Remember that we use different test cases to mark your solution. You are free to add your own test cases
to increase your confidence that your solution is correct and robust.
Note 2023-1
Please note that certain IDEs may not be equipped with a markdown renderer,
which could result in incorrect display of all the information. To ensure accurate
viewing, we recommend accessing the markdown content directly from GitLab
using your web browser.
1
3. EscapedState: If a participant successfully solves all riddles, they will be
transitioned to the EscapedState.
• In this state, RiddleException should be thrown if solveRiddle is
called.
Note:
1. If a riddle has been solved but passed as an argument to solveRiddle
again, a RiddleException should be thrown.
2. A participant can choose any riddle to solve at a time. The argument
whichRiddle of the solveRiddle method indicates to which riddle he/she
submits an input in the riddleList.
Your task: 1. Implement the InProgressState, HelpState, and
EscapedState classes, and make any changes needed in accordance with
the UML (You may need to make changes to complete the class signature,
but are not allowed to change the name of the class). 3. Uncomment the
provided line this.state = new HelpState() in the solveRiddle method of
the Participant class.
Some basic tests have been provided in the ParticipantTest class. You can
use them to clarify your understanding and increase your confidence that your
solution is correct.
Part 2b) Implement the Observer Design Pattern in the context of the Escape
Room. The goal is to create a system where an observer is notified when a
participant either asks for help or escapes successfully. Additionally, the ob-
server should be able to provide information on whether a specific participant
has asked for help or escaped.
In the provided Observer interface, - methods updateHelp and updateEscape
will be called when a participant asks for help and has escaped, respectively. -
methods hasAskedForHelp and hasEscaped checks whether a specific partici-
pant has asked for help or escaped, respectively.
Your tasks: 1. Create and implement the GameMaster class according to the
UML Diagram. - The class must have a package header of package Q1; in
the first line of the code file. 2. Modify the Participant class: - Create the
missing attribute and method shown in the Participant class described in the
UML diagram, and - Update the askForHelp method: notify all the observers
when a specific participant asks for help. - Update the solveRiddle method:
notify all the observers when a specific participant escapes.
• Some basic tests have been provided in the ObserverTest class. You can
use them to clarify your understanding and increase your confidence that
your solution is correct.
– Uncomment the following two lines in the ObserverTest class.
observer = new GameMaster();
participant.registerObserver(observer);
2
You are expected to update the following files and push them (and
only them) to GitLab:
• RiddleCheckAnswerTest.java
• InProgressState.java
• HelpState.java
• EscapedState.java
• GameMaster.java
• Participant.java
3
2023 - 1: Q2 - Data Persistence, Tokenization/Parsing, and
Data Structure
In this question, we will read and process list elements in markdown files
(.md). For simplicity, we only tackle two specific types of list elements of a
strict syntax. Please pay attention to the syntax as defined in this instruction
instead of your own understanding of markdown.
Introduction - List Elements in Markdown Files
List elements can be represented as follows. For unordered lists,
- Element A
- Element B
- Element C
- Element D
- Element E
For ordered lists,
1. Element A
2. Element B
3. Element C
4. Element D
5. Element E
Here, the list elements must follow a fixed indentation: - Elements at the first
level (level=1) shall have no prefixing spaces, and - elements at the next level
must have exactly 4 spaces. (and so on, where elements at level l have exactly
4 x (l-1) spaces before them.)
Note: the index for ordered lists must be a number (integer) (e.g., 1. Element A,
1 is the index (attribute number) for ‘Element A’). You may disregard the follow-
ing cases: - more than one list item in the same line - items at an invalid indenta-
tion level (e.g., with 3 prefix spaces), OR - items at an invalid indentation level
relative to its predecessors/successors, e.g., 1. Element 1 2.
Element Too Far (Will Not Happen)
However, there could be empty lines or with only whitespaces (not a token),
and mixed (ordered and unordered), nested list elements, e.g., - Element 1
- Element 2 1. Element 2A 2. Element 2B 1.
Element 3
You may also refer to the example markdown files within the data directory.
1
• Complete the read() method of the MDFileReader class.
• (Note: you may use any java.io packages)
Part 2) Tokenizer
Complete the next() method of the MDTokenizer class to perform a tokeniza-
tion process. The next() method should identify all tokens and their associated
values (e.g., for an item without indentation (no prefix spaces), the correspond-
ing value for level is 1). Each token has a tokenType, content, level and
number as implemented in the MDToken class. You may also revise the specified
line in hasNext() if needed.
• The types of tokens (tokenType) are ORDERED_ITEM and UNORDERED_ITEM.
You may ignore the LIST_ROOT token type as it is only used in Parts 3
and 4 of this question.
• You may find some basic tests in the given MDTokeniserTest class.
Part 3) Parser and Data Structure
The parser shall take in a tokenizer and process the tokens generated from it.
In particular, you should create a data structure (see ListElementsTree class)
that contains all the tokens inserted into it and retains all the parent-children
relationships and the order of the list elements.
The skeleton of the ListElementsTree class has already been completed. You
must complete the parse() method of the MDParser class. - Use the provided
methods to create the tree and insert elements into it. - A root node (token
type LIST_ROOT) is always given to hold the list of elements. - The nodes of the
trees are not ordered by their values, but each element should be inserted into its
parent as indicated by the tokenizer, which should reflect the structure of the md
file. - The tree and also the nodes have been defined in the ListElementsTree
class. - No test cases are provided as they would reveal the expected answer.
Optionally, you can create your own tests to increase your confidence in your
solution.
Illustration - The expected structure of the ListElementsTree to be created
Taking the following MD files as an example (Note: this is a valid list that fulfill
the syntax set out in this question),
1. I
2. Love
- Software
- Construction
3. So
2. Very
9. Muchhhhhhh
9. REALLY !!!
- �
- (���)
2
- �
After tokenization, your MDParser should process the tokens and insert them
into a ListElementsTree as follows.
Part 4) Data Structure
Implement the preOrderWalk() method within the ListElementsTree class.
Hint: You may add helper methods within the Node class if needed.
Pre-Order traversal at a node entails: visit the current node, then perform
pre-order traversal from its leftmost children to the rightmost children.
For instance, the expected order of nodes in the previous example is illustrated
as follows:
Note that you should exclude the root node of the tree (of LIST_ROOT
type) from the returned list. You may find more details in the given
ListElementsTreeTest.java.
***
You are expected to update the following files and push them (and
only them) to GitLab:
• MDFileReader.java
• MDTokeniser.java
• MDParser.java
• ListElementsTree.java
3
Q2 2022-1 - Design Patterns & Coding Skills (25 marks)
The given code implements a quote calculator that compares the quotes offered
by two express companies and gives the best quote for delivery. The express
companies offer quotes for a parcel delivery based on the integer weight of the
parcel and the integer distance from the express companies to the parcels’
destinations.
Each express company has a delivery radius, within which the companies offer
quotes only based on the weight of the parcel. If the distance is greater than
the radius, the companies charge additional fees for the distance based on the
formula: AdditionalDistanceFees = ratePerDistanceUnit * Distance
The distance between two integer points (x1, y1) and (x2, y2) can be calcu-
lated using the Euclidean distance formula: Distance = sqrt((x1-x2)^2 +
(y1-y2)^2) where sqrt is square root operation, ^2 is the power of 2. The ex-
press companies charge the distance fees based on the round-up distance values
if the calculated distance is fractional. For example, if the calculated distance
is 3.1, then round it up to 4 as the distance value.
The companies sets several weight intervals and each weight interval has a quote
rate. The total quote is the sum of partial quotes of all the intervals, where the
partial quote for each interval is proportional to the part of weight falling in
that interval. For example, for the following quote scheme:
• 0 < weight <= q1: rate=r1
• q1 < weight <= q2: rate=r2
If the weight falls in the interval of (0, q1], the total quote should be Q=weight
* r1. If the weight falls in the interval of (q1, q2], the total quote should be
Q=q1 * r1 + (weight - q1) * r2:
Here is the quote scheme of the express company A:
• 0 < weight <= 20kg: rate=$1.3
• 20kg < weight <= 40kg: rate=$1.7
• 40kg < weight <= 60kg: rate=$2.4
• weight > 60kg: rate=$3.2
Beyond the radius, the company A charges an extra (ratePerDistanceUnit=$1)
for each distance unit.
Here is the quote scheme of the express company B: Different from A, this
company has a constant quote $46 for weights that are no more than 30kg.
For weights higher than 30kg, the strategy is the same as that of A, but with
different rates and intervals.
• 0 < weight <= 30kg: quote is constant at $46
• 30kg < weight <= 40kg: rate=$1.5
• 40kg < weight <= 50kg: rate=$2.1
• 50kg < weight <= 60kg: rate=$2.9
1
• weight > 60kg: rate=$3.6
Beyond the radius, the company B charges an extra (ratePerDistanceUnit=$1.1)
for each distance unit.
QuoteCalculator class has a bestQuote() method that compares the quotes
of the two express companies and yields the best quote (the lower quote). The
methods calculateQuote() in CompanyA.java and CompanyB.java are respec-
tively intended to calculate the quotes of the two companies based on the above
quote schemes. Note that if the quotes offered by two companies are equal,
always choose the express companyA.
Moreover, the express companies have specific prohibited item list and need to
perform a safety check on the items in parcels before calculating quotes. You
are expected to throw an IllegalParcelItemException when there are any
items prohibited by the companies.
Please refer to the given test cases in ParcelTest.java for more details.
Please try your best to return a value for the required methods,
e.g. 0 or null, to make sure your solutions do compile if you
have trouble in providing the solutions. Otherwise, you may be
subject to a mark loss due to compile errors.
2
2021-2 q3: You may recognise the Parcel class (in parcel folder) from the mid-
semester exam, it has been modified slightly for the purpose of this exercise and
now contains the following fields:
• id: an integer that identifies the parcel
• weight: the weight of the parcel
• allowedDays: the maximum allowed days for the parcel to be delivered
• sender: the sender of the parcel
• recipient: the recipient of the parcel
The sender and recipient fields are now of type class Person which has the
following field:
• location: the location of the person denoted by an X and Y coordinate
in kilometres
All parcels must pass through a common warehouse located at [20,10] (as seen
in general case below). Distance is calculated using the standard Euclidean
distance:
DistanceFormula.png
General case:
ParcelGeneral
Example 1: Sender is at position [-10,50], Recipient is at position [70,130]
ParcelExample1
Example 2: Sender is at position [32,5], Recipient is at position [180,-290]
ParcelExample2
Task 1:
Impose a ‘natural order’ on Parcel using the CompareTo method in the Parcel
class. The ordering of parcels to be implemented is defined by:
• The distance from the Warehouse to the Recipient (highlighted in
green in the above image) is in ascending order
Hence since 130km is less than 340km, then we know that the parcel in Example
1 should come before the parcel in Example 2.
1
The CompareTo(Parcel other) method compares two parcels. If the other
parcel should come before this parcel then the CompareTo method should
return a positive int. Conversely, if the other parcel should come after this
parcel then the CompareTo method should return a negative int. And finally,
if the ordering between two parcels is arbitrary (ie. if the relevant distance is
equal) then the CompareTo method should return zero.
Hint: The getDistance method in the CartesianCoordinate class might be
helpful.
You are only allowed to add methods and variables to the Parcel.java file for
this task, do not change the class structure.
Task 2:
Create an Iterator that implements a pre-order walk over a Binary Search
Tree of parcels. The class for the iterator is already created for you (see in-
ner class IteratorPreOrder in the ParcelBST), your job is to implement the
methods hasNext() and next().
You may recognise the implementation of the immutable BinarySearchTree
class from your labs. The ParcelBST class is essentially a BinarySearchTree
that holds Parcels. Your iterator implementation needs to somehow store which
Parcel it is up to. When the method next() is called, your iterator implemen-
tation should return the next parcel in the pre-order walk.
If next() is called and there are no parcels left in the iteration, then it should
throw a new instance of NoSuchElementException. The hasNext() method
should return true if there are parcels left in the iteration and false if not.
You are only allowed to add methods and variables to the ParcelBST.java file
for this task, do not change the class structure.
2
Q2 - Software Testing 2022-2 [30 marks] Implement JUnit test
cases for ALL METHODS (except the constructor methods) of the classes
Person and PersonRepository that is Branch Complete [5 marks]. For the
calcInsurancePrice() method of the Person class [15 marks] and the save()
method of the PersonRepository class [10 marks], write the MINIMUM
number of JUnit test cases that is Branch Complete. Write your test cases in
the PersonTest.java and PersonRepositoryTest.java files, respectively.
Note that:
Each execution of an assertion counts as a single test case, therefore loops that
execute the same assertion multiple times count as multiple tests.
&& and || operators introduce their own branches.
All test cases must pass the JUnit test to get full marks.
You must use JUnit4 to write your test cases.
Each test file will be run separately. This means that the test cases created in the
PersonRepositoryTest class will only be used to test thePersonRepository
class, and the test cases created in the PersonTest class will only be used to
test the Person class.
Upload the files: PersonTest.java and PersonRepositoryTest.java to Wat-
tle for marking.
1
Q3 2022-1 - Tokenisation & Parsing & Tree (30 marks)
The provided code implements a simple compiler that compiles and executes a
series of commands. The compiler interacts with a binary-tree based memory.
The memory is initialised as empty. There are three types of commands with
the syntax as below:
• LOAD key;: loads the value stored in an address referenced by the string
key in memory. If the key does not exist, return null.
• SAVE value TO key; : saves the value to an address referenced by the
string key in memory.
• SUM pattern TO key; : adds up all the values in addresses referenced
by the keys satisfying the string pattern and saves the sum value to an
address referenced by the string key. If no keys satisfy the given pattern,
save 0 to memory.
The string pattern can be: * a wildcard character * indicating 0 or at least 1
letter or digit. * a series of letters and digits along with at most one wildcard
character, e.g. abc, abc*, *abc, a*c. For example, all of aasdbc, abbbc, abc,
a2c, ac satisfy the pattern a*c. bac does not satisfy the pattern a*c because
it does not start with the letter a. The pattern * references all the keys in
memory.
Note that you are not allowed to use regex libraries to achieve the pattern search.
We will check the usage of regex-related libraries and assign zero mark for
those who use it. Tips: If you have some difficulties in handling the
commands with a wildcard character, it would be better to adapt
your solutions for the commands without a wildcard character.
We will prepare different marking test cases to evaluate your
solutions. This will help you get partial marks but not lose all
the marks for this question.
LOAD, SAVE, SUM, TO, TERMINATOR, PARAMETER are the defined keywords of the
commands. key, value, and pattern are the parameters of the commands.
The semi-colon ; is the terminator.
Part 1) Implement the next() method of the Tokeniser class to perform
a tokenisation process. The next() method should be able to identify the
keywords and parameters of the commands. The token types are defined in
the Token.java class. The keywords and parameters are separated by at least
one space or special symbol, where a special symbol can be any symbol except a
letter, a digit, the wildcard character * or the terminator ;. For instance, ^%&$@
are considered as special symbols. You are expected to return valid tokens that
do not include any spaces or special symbols.
Please find more details in the given TokeniserTest.java.
Part 2) Implement the parseCmds() method of the Parser class to create three
types of commands from the tokens: * LoadCommand contains one parameter,
1
a string key. * SaveCommand contains two parameters, a string key and a
non-negative integer value. * SumCommand contains two parameters, a string
pattern and a string key.
Please find more details in the given ParserTest.java.
Part 3) Implement the find() and invertedPreOrder() methods of the BST
class to realise the underlying operations of binary search tree. find() aims
to find a particular node based on a given key. invertedPreOrder() aims to
perform an inverted pre-order traversal of the tree. Note that the traversal of
an inverted pre-order should be: root, right child, left child.
Please find more details in the given BSTTest.java.
Part 4) Implement the load(), save() and sum() methods of the Executor
class to execute the parsed commands. You are required to use find() and
invertedPreOrder() as helper methods. For instance, invertedPreOrder()
method needs to be used to loop through all the keys stored in the tree-based
memory.
Please find more details in the given ExecutorTest.java.
IMPORTANT NOTES: * The string key parameters are composed of letters and
digits, whereas the value parameters are non-negative integers. * The key or
value parameters DO NOT include a wildcard character. * The keywords are
all case INSENSITIVE, whereas the key parameters are case SENSITIVE. HINT:
you can use toLowerCase() or toUpperCase(), etc. defined in the String.class
to compare strings without care for case sensitivity. * The keywords will not
appear in the parameters. * At least one space or special symbol between the
keyword and parameter is allowed. * Each single command is terminated by
a semi-colon ;. * A series of single commands can be concatenated together in
any order. * All the commands in the given and marking test cases are valid.
You don’t need to consider the invalidity of the commands.
We give some examples of valid commands below: * LOAD a; * save 100
to a; * save 10 to&^ variable!@#$%^& ; Load variable ; Sum
vari* To ret ;
We may not give all the valid test cases. Feel free to add more test cases to test
the robustness of your solutions.
Please try your best to return a value for the required methods,
e.g. 0 or null, to make sure your solutions do compile if you
have trouble in providing the solutions. Otherwise, you may be
subject to a mark loss due to compile errors.
2
• next() method in the Tokeniser.java class
• parseCmds() method in the Parser.java class
• find(), invertedPreOrder() methods in the BST.java class
• load(), save(), sum() methods in the Executor.java class
3
Q2 - Tokenisation and Parsing 2021-2 q2
The code provided implements a simple compiler that compiles and executes a
series of commands listed below. There are two types of commands with the
syntax as below:
• LOAD object_key FROM file_name;
• SAVE object_key TO file_name;
where object_key is a string key referencing a certain object stored in a
database and file_name is a string that is made of a file name and the XML
file extension .xml.
This compiler aims to use the two commands to load and save a list of
persons objects, where each Person object has four fields, name, gender, age,
occupation. For example,
• LOAD persons FROM persons.xml, which loads a list of persons from a
persons.xml file into the database
• SAVE persons TO persons.xml, which saves a list of persons to a
persons.xml file from the database
LOAD, FROM, SAVE, TO, TERMINATOR, PARAMETER are the defined keywords of the
commands. persons, persons.xml are the parameters of the commands. The
terminator is a semi-colon ;. Note that object_key and file_name are not
fixed to the given persons and persons.xml as we will use different parameters
in the marking test cases to test the robustness of your solutions. But the
objects to be stored in the database will be fixed to Person instances.
Part 1) Implement the next() method of the Tokeniser class to perform a to-
kenisation process. The next() method should be able to identify the keywords
and parameters of the commands. The tokens and the types are defined in the
Token.java class.
Please find more details in the given TokeniserTest.java.
Part 2) Implement the parseCmds() method of the Parser class to create two
types of commands from the tokens: * LoadCommand contains two parameters,
a key indicating the object_key, e.g. persons, and a fileName indicating the
file_name, e.g. persons.xml. * SaveCommand contains two parameters, a key in-
dicating the object_key, e.g. persons, and a fileName indicating the file_name,
e.g. persons.xml.
Please find more details in the given ParserTest.java.
Part 3) Implement the loadFrom(), saveTo() methods of the Executor class
to execute the parsed commands.
You are required to follow the format of the given example xml file example.xml.
The variables KEY_XXX in Person.java class give the tag names of the elements
for the xml file. Note that indent property of the xml transformer is optional,
1
you are allowed to uncomment it in saveTo() method of Executor.java class
to make the files more readable.
Please find more details in the given ExecutorTest.java.
IMPORTANT NOTES: * The keywords are all case insensitive, whereas
the parameters are case sensitive. HINT: you can use toLowerCase() or
toUpperCase(), etc. defined in the String.class to compare strings without
care for case sensitivity. * Each single command is terminated by a semi-colon
;. * Any number of spaces or tabs between the keywords are allowed. * A
series of single commands can be concatenated together in any order. * All the
commands in the given and marking test cases are valid. You don’t need to
consider the invalidity of the commands.
We give some examples of valid commands below: * LOAD persons FROM
persons.xml; * save persons to persons.xml; * LOAD persons
from persons.xml; save persons to persons.xml;
We may not give all the valid test cases. Feel free to add more test cases to test
the robustness of your solutions.
2
2023 - 2: Q2 - Object-oriented Decisions
Spiders are a concern for Australian hikers and tourists alike. It is often impor-
tant to be able to determine exactly which kind of spider you encounter, because
this affects what kind of behaviour or medical treatment may be necessary. This
piece of software is designed to solve that problem.
This problem considers binary decision trees operating on Spiders. Each deci-
sion step has exactly two branches, based on whether a spider has a particular
property (listed within the enum Spider.Property) or not. These branches may
lead to another decision, or to a terminal node, which reports the name of the
species the spider has been classified as.
Tasks
Part a) Classify Spiders
Implement the function classify in Node and its subclasses. The methods take
as input a Spider and, by following the decision tree until a terminal node is
reached, is able to classify the spider.
Part b) Stringify the Decision Node
Implement the function DecisionNode.toString, which outputs a well-
formatted String representation of a given decision tree, with the following
template format:
Is black?
| Yes: Has coloured area?
| | Yes: Red-back
| | No: Huntsman
| No: Has coloured area?
| | Yes: Peacock
| | No: Daddy long-legs
Every aspect of your output must match the above specification, in-
cluding the indenting and punctuation. You may wish to reference
Spider.propertyToString and TerminalNode.outcome to generate parts of
the output.
Since this method is implemented in the class DecisionNode, you can assume
that the tree contains at least one decision. Of course, the terminal nodes must
also be included in your output.
Part c) Classifier Factory
The class ClassifierFactory uses the factory design pattern to build decision
trees that are able to distinguish between a given set of spiders. Implement this
with ClassifierFactory.createClassifier.
Users must be able to distinguish between spiders quickly and efficiently. There-
fore, for this part, you will be marked not only on the correctness of the resulting
1
decision tree, but also on its height. That is, you should construct the correct
classifier that minimises maximumDecisions. Partial marks will be given for less
efficient classifiers.
You may assume that the input to createClassifier is a valid non-empty set,
in which every spider has a different speciesName.
• You may find test cases in ClassificationTests.java to help with your
code development. The marking test cases for this question will be highly
similar to that of the ones provided, in terms of the aspects of assessment
.
You are expected to update the following files and push them to
GitLab:
• Node.java
• DecisionNode.java
• TerminalNode.java
• ClassifierFactory.java
2
Q1 - Tokenization and Tree Build 2020-2
[30 marks]
Part 1 [20 marks]) Implement the 'next()' method of the 'MyTokenizer' class to perform a tokenization process. The 'next()'
method should be able to identify the following token types: upper case words, lower case words, short camel case
words, long camel case words, integers, and non-alphanumeric characters.
A token and the token types are defined in the 'Token.java' class.
Definitions:
Example: Consider the text: 'i am the KING of THE castle. The caStle is my HOME. I am 10 #@ 1234'.
Part 2 [10 marks]) Implement the 'build()' method of the 'TreeBuilder' class to create a tree following the specifications
below:
The 'build()' method must create and return a tree containing all upper case words extracted from the input string.
The key of each node in the tree corresponds to the length of the upper case word.
If two or more distinct upper case words have the same length, those words must be added to the same node (in
a list of strings in that node). For example, if a string contains the words HOME and KING, then HOME and KING
should be at the same node of the tree, with key 4.
The build method receives a string as input and returns a tree containing only the upper case words extracted
from the input string.
You must use the 'MyTokenizer' class to help you extract each upper case word from the input string and insert it
in the tree you will return.
Upload the files: 'MyTokenizer.java' and 'TreeBuilder.java' to Wattle for marking.
Note that you are expected to give a generic solution that fulfils the question requirements. You are encouraged to create
your own test cases locally to check your solutions. We will use different test cases from the given ones to evaluate your
solutions.