cs1010s Final Apr21 PDF
cs1010s Final Apr21 PDF
CS1010S—Programming Methodology
2020/2021 Semester 2
INSTRUCTIONS TO STUDENTS
1. Please write your Student Number only. Do not write your name.
2. The assessment paper contains FIVE (5) questions and comprises TWELVE (12) pages
including this cover page.
3. Weightage of each question is given in square brackets. The maximum attainable score
is 100.
4. This is a CLOSED book assessment, but you are allowed to bring ONE double-sided
A4 sheet of notes for this assessment.
5. Write all your answers in the space provided in the ANSWER BOOKLET.
6. You are allowed to write with pencils, as long as it is legible.
7. Marks may be deducted for i) unrecognisable handwriting, and/or ii) excessively long
code. A general guide would be not more than twice the length of our model answers.
8. Common List and Dictionary methods are listed in the Appendix for your reference.
CS1010S Final Assessment
2
CS1010S Final Assessment
3
CS1010S Final Assessment
A. [Warm-up] The hash function is an essential component of all blockchains. Since we have
not studied cryptography in CS1010S, we settle for a very simple and naive hash function.
Implement the function hash(string) that takes as input a string ( str ). Return the sum of
all the ordinals of each character, converted to a string (instead of an integer). You may use the
ord function for this question. [4 marks]
Sample execution:
>>> ord("D")
68
>>> ord("d")
100
>>> hash("Dd")
"168"
>>> hash("dec")
"300"
B. Each block in the blockchain contains a name ( str ), a date ( str ), and a hash ( str ). A
blockchain could be arbitrarily long.
Implement the function, get_names(blockchain, date) that takes as input a blockchain
( list of list ), and a date ( str ). Return the list of all the names in the given blockchain
who were vaccinated before or equal to the given date. Return the names in the same order of
appearance in the blockchain. [4 marks]
Note: Since the dates are in ISO date format, you can directly compare the strings
Sample execution:
>>> "2021-01-01" < "2021-04-01" # 1st Jan 2021 before 1st Apr 2021
True # ISO format allows for direct comparison
4
CS1010S Final Assessment
C. The hash of each block in the blockchain is derived by concatenating the name and date of
the current block, with the hash of the previous block. This way, a block in the chain cannot be
modified without affecting the entire chain.
For example, adding the name "Eshin" on the date "2021-04-29" to the blockchain in the
example above will modify and return the existing blockchain to include a new block:
>>> add_block("Eshin", "2021-04-29", blockchain)
>>> blockchain
[["Ben", "2021-02-28", "815"], ["Kenghwee", "2021-04-01", "1456"],
["Waikay", "2021-04-17", "1313"], ["Jon", "2021-04-29", "989"],
["Eshin", "2021-04-29", "1167"]]
The new hash value "1167" was generated from the hash of the strings "989", "Eshin", and
"2021-04-29" concatenated together.
Implement the function add_block(name, date, blockchain) that appends a new block
containing the name, date and correct hash value to the end of the blockchain. You may assume
that the blockchain contains at least one block. [4 marks]
D. Using blockchain technology allows us to verify the validity of the blocks in the chain.
Implement the function is_valid(blockchain) that returns True if the blockchain is valid,
and False otherwise. A blockchain is valid if the hash values of each block matches the
expected computed hash value. The previous hash value of the first block is assumed to be an
empty string "". [4 marks]
E. In order to verify if a person has been vaccinated, we need a way to retrieve the date of
vaccination. Implement the function date_vaccinated(name, blockchain) that returns
the date when the person was innoculated with the vaccine, or None if the blockchain is not
valid or if the person does not have any record on the blockchain. You may assume that names
are unique. [4 marks]
F. The current implementation of hash not good since Waikay can be substituted with his evil
twin Wayaki, and the blockchain will still be valid. In fact, Wayaki gleefully demonstrates this:
blockchain[2][0] = "Wayaki"
In order to prevent changes in the names in the blockchain, Ben Bitdiddle decides to change
the implementation of the blockchain to list of tuples.
improved_blockchain = [
("Ben", "2021-02-28", "815"), ("Kenghwee", "2021-04-01", "1456"),
("Waikay", "2021-04-17", "1313"), ("Jon", "2021-04-29", "989")
]
Is this implementation now safe from any form of tampering by the evil twin Wayaki? If this is
safe, state yes and explain why. Otherwise, state no and demonstrate with some code how the
blockchain may still be tampered. [2 marks]
5
CS1010S Final Assessment
blank ⇥2 D ⇥4 H ⇥2 L ⇥4 P ⇥2 T ⇥6 X ⇥1
A ⇥9 E ⇥12 I ⇥9 M ⇥2 Q ⇥1 U ⇥4 Y ⇥2
B ⇥2 F ⇥2 J ⇥1 N ⇥6 R ⇥6 V ⇥2 Z ⇥1
C ⇥2 G ⇥3 K ⇥1 O ⇥8 S ⇥4 W ⇥2
Source: Wikipedia
We can represent a bag of tiles of the current distribution using a list-of-lists, where the index
of the outer list represent the number of tiles of each of the characters in the inner list. E.g., the
above distribution will be represented as follows (with space representing blank tiles):
bag = [[],
['K', 'J', 'X', 'Q', 'Z',],
[' ', 'F', 'H', 'V', 'W', 'Y', 'B', 'C', 'M', 'P'],
['G'],
['D', 'L', 'S', 'U'],
[],
['N', 'R', 'T'],
[],
['O'],
['A', 'I'],
[],
[],
['E']]
During the game, tiles are drawn from the bag, which changes the distribution of the remaining
characters.
A. [Warm-up] Implement the function total_tiles(bag) that takes as input a bag of tiles
in the above-mentioned representation, and returns the total number of tiles currently in the
bag. [4 marks]
B. The function remove(char, bag) takes as input a character, and a bag of tiles (in the
above-mentioned representation). If the bag contains one or more of the given character, one
tile of the character is removed and the bag is updated to represent this new distribution, and
True is returned. Otherwise, if the bag does not contain the character, False is returned.
Provide an implementation of the function remove . Note there is no need to remove empty
lists from the outer list. [4 marks]
6
CS1010S Final Assessment
C. The current list-of-list used to represent the distribution of tiles in a bag is not very efficient.
It would be better if we can use a dictionary to represent the distribution using the characters
as keys, and the values as their quantity.
For example, the initial distribution of the English-language Scrabble would be:
{' ': 2, 'A': 9, 'B': 2, 'C': 2, 'D': 4, 'E': 12, 'F': 2, 'G': 3, 'H': 2,
'I': 9, 'J': 1, 'K': 1, 'L': 4, 'M': 2, 'N': 6, 'O': 8, 'P': 2, 'Q': 1,
'R': 6, 'S': 4, 'T': 6, 'U': 4, 'V': 2, 'W': 2, 'X': 1, 'Y': 2, 'Z': 1}
D. Implement the function to_list(bag) , that takes in a bag of tiles in the dictionary rep-
resentation, and returns a bag in the list-of-list representation. Basically it does the reverse of
the to_dict function. Hint: take note of aliasing when creating an empty list-of-lists.
[4 marks]
E. Sometimes players want to play Mega Scrabble by combining tiles of different bags into
one bag. Implement the function combine(a, b) that takes two bags of tiles in the list-of-lists
representation, and returns a new bag of tiles, also in the list-of-list representation.
[6 marks]
F. It is not good to have a global variable represent a bag. Instead, the global bag variable
should be used to “clone” new bags which can be used for different Scrabble games. To prevent
players from peeking into these cloned bags, we can hide them inside a function.
The function new_game(bag) takes as input a bag of tiles (in whichever representation you
wish to use), and returns a function that draws a random tile from a “cloned” bag and returns
the character drawn. The tile is removed from the “cloned” bag, and not from the original bag
given. If the bag has no more tiles, False is returned. For example:
>>> game = new_game(bag)
>>> game()
'L' # letter drawn at random
Given the function choice(seq) that takes in a sequence and returns a random element of the
sequence, provide an implementation for the function new_game . Note that you are not to use
any other randomisation function other than choice . [6 marks]
7
CS1010S Final Assessment
A. Clarence found something odd with the current implementation. He gets an error when he
executes the following lines:
>>> rainbow_dash = Pegasus(20)
>>> rainbow_dash.move()
Let's go!
xxxxError: xxxxx
But if he gets his pony to fly first, he does not get any error.
>>> rainbow_dash = Pegasus(20)
>>> rainbow_dash.fly()
>>> rainbow_dash.land()
>>> rainbow_dash.move()
Let's go!
Explain the cause of the error and why it does not occur in the latter code. Implement the code
to fix this according to OOP principles, i.e. redundant code will be penalised. [4 marks]
8
CS1010S Final Assessment
B. A Unicorn is a Pony that has magical powers. It has a special reserve of mana energy
that allows it to be consumed in lieu of its regular “Pony energy” when the consume method is
called. This mana energy is only good for 3 uses. Once her mana energy is used up, the normal
behaviour of consumption energy resumes.
Example:
>>> rarity = Unicorn(10)
>>> rarity.move() # consumes mana
Let's go!
>>> rarity.consume() # consumes mana
>>> rarity.consume() # consumes mana
>>> rarity.energy
10 # still has 10 energy
>>> rarity.move()
Let's go!
>>> rarity.move()
Need to rest
Provide an implementation of the class Unicorn using OOP principles. Redundant code or
methods will be penalised. [6 marks]
She is also unsure whether the order of the super classes Pegasus and Unicorn makes any
difference.
Sunset Shimmer thinks Twilight is being silly as classes should always contain methods to
work. And besides, the ordering of the super classes makes no difference here.
Explain in detail if Twilight Sparkle’s idea is correct, and whether the order of the super classes
matter. You can list some sample execution to aid your explanation. [6 marks]
— END OF PAPER —
9
CS1010S Final Assessment
Appendix
Parts of the Python documentation is given here for your reference.
List Methods
• list.append(x) Add an item to the end of the list.
• list.extend(iterable) Extend the list by appending all the items from the iterable.
• list.insert(i, x) Insert an item at a given position.
• list.remove(x) Remove the first item from the list whose value is x. It is an error if
there is no such item.
• list.pop([i]) Remove the item at the given position in the list, and return it. If no
index is specified, removes and returns the last item in the list.
• list.clear() Remove all items from the list
• list.index(x) Return zero-based index in the list of the first item whose value is x.
Raises a ValueError if there is no such item.
• list.count(x) Return the number of times x appears in the list.
• list.sort(key=None, reverse=False) Sort the items of the list in place.
• list.reverse() Reverse the elements of the list in place.
• list.copy() Return a shallow copy of the list.
Dictionary Methods
• dict.clear() Remove all items from the dictionary.
• dict.copy() Return a shallow copy of the dictionary.
• dict.items() Return a new view of the dictionary’s items ( (key, value) pairs).
• dict.keys() Return a new view of the dictionary’s keys.
• dict.pop(key[, default]) If key is in the dictionary, remove it and return its value,
else return de f ault. If de f ault is not given and key is not in the dictionary, a KeyError
is raised.
• dict.update([other]) Update the dictionary with the key/value pairs from other,
overwriting existing keys. Return None .
• dict.values() Return a new view of the dictionary’s values.
10
CS1010S Final Assessment
Scratch Paper
11
CS1010S Final Assessment
Scratch Paper
— H A P P Y H O L I D A Y S ! —
12
CS1010S — Programming Methodology
School of Computing
National University of Singapore
2
Answer Sheet CS1010S Final Assessment
Question 1A [5 marks]
a = [0]
b = [1, [2]]
a.append(b[1])
print(a)
a.extend(b)
print(a)
a[1] = 3
b[1] = 4
print(a)
Question 1B [5 marks]
d = {1: 2, 2: 0, 3: 1}
def descend(v):
if v > 0:
descend(d[v])
print(v)
descend(3)
Question 1C [5 marks]
s = "lever"
while s:
print(s)
if s[0] == s[-1]:
s = s[1:-1]
elif s[0] not in s[1:]:
s = s[1:]
else:
s = s[:-1]
3
Answer Sheet CS1010S Final Assessment
Question 1D [5 marks]
x, o = "x", "o"
def f():
return x + o
def g(x, o):
x = f()
print(x)
print(o)
o = f()
return x + o
print(g(o, x))
Question 1E [5 marks]
def caution(x):
try:
return x[2] * 2
except IndexError:
return x
except TypeError:
return "type"
print( caution("CS1010S") )
print( caution([1, 2]) )
print( caution({1: 2}) )
Question 1F [5 marks]
def f(x):
print(x)
return lambda y: g(y) + x
def g(x):
print(x)
return lambda y: y + x
print(f(1)(2)(3))
4
Answer Sheet CS1010S Final Assessment
Question 2A [4 marks]
def hash(string):
Question 2B [4 marks]
Question 2C [4 marks]
5
Answer Sheet CS1010S Final Assessment
Question 2D [4 marks]
def is_valid(blockchain):
Question 2E [4 marks]
6
Answer Sheet CS1010S Final Assessment
Question 3A [4 marks]
def total_tiles(bag):
Question 3B [4 marks]
Question 3C [4 marks]
def to_dict(bag):
7
Answer Sheet CS1010S Final Assessment
Question 3D [4 marks]
def list(bag):
Question 3E [6 marks]
8
Answer Sheet CS1010S Final Assessment
Question 3F [6 marks]
9
Answer Sheet CS1010S Final Assessment
10
Answer Sheet CS1010S Final Assessment
11
Answer Sheet CS1010S Final Assessment
12