Test: Sample Solutions
- Checking Speller
- Code Reviews
- Duo Mobile
- Emojicode
- Harvard Pep Squad
- Imagineering
- International Obfuscated C Code Contest
- Reinventing Some Wheels
- View Source
- XCheck
Checking Speller
-
To close
file
, you can rewrite line 12 aswith open(dictionary, "r") as file:
indenting lines 13 and 14 thereunder.
-
If you’d like
check
to be case-insensitive, you could change line 5 to be:if word.lower() in words:
If you can’t assume the words in
dictionary
will be lowercase, though, you should also change line 14 to be:words.append(line.rstrip().lower())
-
Because
in
evaluates toTrue
orFalse
, you could reimplementcheck
asdef check(word): return word in words
or as
def check(word): return word.lower() in words
per issue #2.
-
You can reimplement
size
asdef size(): return len(words)
since
len
will return the length ofwords
in \(O(1)\) time (since alist
keeps track of its own length, andlen
effectively returns that value).
-
Because
words
is alist
, checking whetherword
is in it involves linear search, which takes \(O(n)\) time. To achieve \(O(1)\) time (on average), changewords
to be aset
:words = set()
And then change line 14 to be:
words.add(line.rstrip())
Code Reviews
- Because
s
is never assigned a value, it contains a garbage value, andscanf
will thus try to write to an invalid memory location. To fix the problem, you could usemalloc
to assign tos
the address of a valid block of memory, or you could re-implements
as achar
array of some size. Even then, the user might still input more characters than you anticipated, so best to avoidscanf
altogether, using a function likegetc
to get input one character at a time so that you can grows
as needed, as withrealloc
.
- If
malloc
happens to returnNULL
, thenn
would beNULL
, and dereferencing it (in order to assign13
tonumber
) would crash the program. To fix the problem, you should check whethern
isNULL
and only assign values tonumber
andnext
if it is not.
- This code is poorly designed because it submits the user’s password via
GET
, potentially storing it in the user’s history (in the browser’s address bar) where others could see it. To fix the problem, changeget
topost
.
-
This code is vulnerable to a SQL injection attack because it doesn’t escape the value of
q
before using it in a query. To fix the problem, rewrite the line asresults = db.execute(f"SELECT * FROM books WHERE title LIKE ?", q)
so that
db.execute
escapes the value first.
- This code does not check whether
username
andpassword
actually have (non-None
) values; it should before callingdb.execute
. The code also does not check whether theINSERT
has failed, as might happen ifusername
is already taken; it should by checking the return value ofdb.execute
. And the code also storespassword
as plaintext without hashing it first.
Duo Mobile
- A possession factor.
- If a user has, e.g., a knowledge factor (like a password) and a possession factor (like a key fob), then an adversary not only needs to acquire that knowledge, they also need physical access to the user to acquire the possession, which tends to reduce the number of potential adversaries. By contrast, if a user has, e.g., two knowledge factors, it’s possible that both could be acquired via just one process (like brute-force guessing). Similarly, if a user has, e.g., two possession factors, it’s possible that both could be acquired via just one process (like theft).
- Requiring an authentication factor like Duo Mobile impacts usability, adding friction: authentication is now a multi-step process requiring that a user not only input a password but also operate a device. If that device is lost, if that device has no reception, or if the device’s battery has died, a user might not be able to authenticate.
- Both the key fob and the app or website could be configured to use the same algorithm to output the same sequence of numbers. Alternatively, both could be configured to output a number based on the current time; so long as the key fob’s clock is synchronized with the app’s or website’s clock, both would output the same number.
Emojicode
- 🏁 is similar to
main
.
- 🍇 and 🍉 are similar to
{
and}
, respectively.
- 😀 is similar to
printf
.
- 🔤 and 🔤 are similar to
"
and"
, respectively.
- ❗️ is similar to a close parenthesis (or a semicolon).
-
import random print(random.randint(1, 10))
-
name = input("🤷 ") print(f"👋 {name}")
-
for i in range(10, 0, -1): print(i)
Harvard Pep Squad
-
import sys if len(sys.argv) != 2: sys.exit(1) with open(sys.argv[1], "r") as file: s = file.read() print(s.count("#"))
-
import sys placards = [] for arg in sys.argv[1:]: with open(arg, "r") as file: placards.append(file.read().splitlines()) for i in range(6): for placard in placards: print(placard[i], end=" ") print()
Imagineering
- By changing
100
to some other value.
- This line of code instantiates (i.e., creates) a new
Boid
object at a random location on the canvas, storing a reference thereto in an array calledboids
.
- “Running” a boid involves associating it with a flock, updating its location on the canvas, wrapping around from one side of the canvas to the opposite side as needed, and drawing the boid on the canvas as a circle.
- You could change
draw
to loop from0
to some value less thanboids.length
(e.g., half of that) in order to run fewer boids.
-
background('#00FFFF');
- By definition of flocking, each boid maintains some separation, alignment, and cohesion with other boids (so that they all cluster together). The implementation of
flock
thus needs access to the whole array ofboids
in order to establish those relationships.
- Any values whereby
alignment
>=max(cohesion, separation)
>0
should suffice.
International Obfuscated C Code Contest
- This function rounds
x
(if non-negative) to the nearestint
, a laround
. It does so by adding0.5
tox
and truncating the floating-point result to anint
, effectively flooring it. For instance, adding0.5
to0.4
would yield0.9
, which would get truncated to0
, while adding0.5
to0.6
would yield1.1
, which would get truncated to1
.
- This function calculates the length of
s
, a lastrlen
. It first assigns the address ofs
tot
and then uses pointer arithmetic to look for, onechar
at a time, the trailingNUL
character. It then subtractss
fromt
in order to count the number ofchar
s in between.
- This function returns \(x^y\), a la
pow
. It first initializesn
to1
, thereafter multiplyingn
byx
a total ofy
times, effectively computingx
to the power ofy
.
- This function converts a number, represented as a string, to an
int
, a laatoi
. It does so by iterating over every digit ins
, from right to left, converting eachchar
to an equivalentint
(by subtracting from each the ASCII value of0
), thereafter multiplying the result by a power of 10 according to its place ins
. For instance, a string like"123"
would be converted to \(3 \times 10^0 + 2 \times 10^1 + 1 \times 10^2 = 123\).
Reinventing Some Wheels
-
void test_isdigit(void) { assert(isdigit('0') == true); assert(isdigit('9') == true); assert(isdigit('A') == false); assert(isdigit('Z') == false); assert(isdigit('+') == false); assert(isdigit('/') == false); }
bool isdigit(char c) { return c >= '0' && c <= '9'; }
-
void test_isalnum(void) { assert(isalnum('A') == true); assert(isalnum('a') == true); assert(isalnum('0') == true); assert(isalnum('9') == true); assert(isalnum('+') == false); assert(isalnum('/') == false); }
bool isalnum(char c) { return isalpha(c) || isdigit(c); }
-
void test_areupper(void) { assert(areupper("ABC") == true); assert(areupper("XYZ") == true); assert(areupper("Abc") == false); assert(areupper("abc") == false); assert(areupper("123") == false); }
bool areupper(char *s) { for (int i = 0, n = strlen(s); i < n; i++) { if (s[i] < 'A' || s[i] > 'Z') { return false; } } return true; }
View Source
- By design, HTML is meant to downloaded from servers to browsers, where it is parsed and rendered client-side. The browser and, in turn, the human using the browser necessarily have access to the HTML itself as a result.
- It’s possible the Social Security numbers (SSNs) were inside HTML tags that were hidden (as via CSS), in HTML tags’
data-
attributes, or in JavaScript variables within the pages.
- By publishing the report right away, the newspaper might have given adversaries an opportunity to download the Social Security numbers before DESE could remove them, thereby putting individuals at heightened risk of identity theft.
- By waiting even longer to publish the report, the newspaper might have given adversaries even more time to discover (on their own) and download the Social Security Numbers, thereby putting individuals at heightened risk of identity theft as well.
XCheck
- A user could simply change the value of
vip
from0
to1
, as via their browser’s developer tools, and then submit the form without moderation.
-
document.querySelector('form').addEventListener('submit', function(e) { let content = document.querySelector('#content').value; if (content.toLowerCase().includes('vaccine') && !vip) { e.preventDefault(); } });
covid
,covid-19
,vaccine
,vaccinate
,vaccinated
,vaccination
, andvaccinations
.
- A user could simply change the value of
vip
fromfalse
totrue
or remove the event listener altogether, as via their browser’s developer tools. And a user could also deliberately misspell these terms (or use synonyms), which the regex wouldn’t detect, in order to spread misinformation.
- This implementation would prevent users who aren’t VIPs from even mentioning
vaccine
(or, with the regex, related terms), even to communicate accurate information.
-
def is_vip(username): rows = db.execute("SELECT vip FROM users WHERE username = ? AND vip = 1", username) return len(rows) == 1
-
UPDATE users SET vip = 0;
- Answers vary.
- Answers vary.