Test: Sample Solutions

Checking Speller

  1. To close file, you can rewrite line 12 as

    with open(dictionary, "r") as file:
    

    indenting lines 13 and 14 thereunder.

  1. 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())
    
  1. Because in evaluates to True or False, you could reimplement check as

    def check(word):
        return word in words
    

    or as

    def check(word):
        return word.lower() in words
    

    per issue #2.

  1. You can reimplement size as

    def size():
        return len(words)
    

    since len will return the length of words in \(O(1)\) time (since a list keeps track of its own length, and len effectively returns that value).

  1. Because words is a list, checking whether word is in it involves linear search, which takes \(O(n)\) time. To achieve \(O(1)\) time (on average), change words to be a set:

    words = set()
    

    And then change line 14 to be:

    words.add(line.rstrip())
    

Code Reviews

  1. Because s is never assigned a value, it contains a garbage value, and scanf will thus try to write to an invalid memory location. To fix the problem, you could use malloc to assign to s the address of a valid block of memory, or you could re-implement s as a char array of some size. Even then, the user might still input more characters than you anticipated, so best to avoid scanf altogether, using a function like getc to get input one character at a time so that you can grow s as needed, as with realloc.
  1. If malloc happens to return NULL, then n would be NULL, and dereferencing it (in order to assign 13 to number) would crash the program. To fix the problem, you should check whether n is NULL and only assign values to number and next if it is not.
  1. 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, change get to post.
  1. 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 as

    results = db.execute(f"SELECT * FROM books WHERE title LIKE ?", q)
    

    so that db.execute escapes the value first.

  1. This code does not check whether username and password actually have (non-None) values; it should before calling db.execute. The code also does not check whether the INSERT has failed, as might happen if username is already taken; it should by checking the return value of db.execute. And the code also stores password as plaintext without hashing it first.

Duo Mobile

  1. A possession factor.
  1. 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).
  1. 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.
  1. 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

  1. 🏁 is similar to main.
  1. 🍇 and 🍉 are similar to { and }, respectively.
  1. 😀 is similar to printf.
  1. 🔤 and 🔤 are similar to " and ", respectively.
  1. ❗️ is similar to a close parenthesis (or a semicolon).
  1. import random
    
    print(random.randint(1, 10))
    
  1. name = input("🤷 ")
    print(f"👋 {name}")
    
  1. for i in range(10, 0, -1):
        print(i)
    

Harvard Pep Squad

  1. import sys
    
    if len(sys.argv) != 2:
        sys.exit(1)
    with open(sys.argv[1], "r") as file:
        s = file.read()
    print(s.count("#"))
    
  1. 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

  1. By changing 100 to some other value.
  1. 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 called boids.
  1. “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.
  1. You could change draw to loop from 0 to some value less than boids.length (e.g., half of that) in order to run fewer boids.
  1. background('#00FFFF');
    
  1. 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 of boids in order to establish those relationships.
  1. Any values whereby alignment >= max(cohesion, separation) > 0 should suffice.

International Obfuscated C Code Contest

  1. This function rounds x (if non-negative) to the nearest int, a la round. It does so by adding 0.5 to x and truncating the floating-point result to an int, effectively flooring it. For instance, adding 0.5 to 0.4 would yield 0.9, which would get truncated to 0, while adding 0.5 to 0.6 would yield 1.1, which would get truncated to 1.
  1. This function calculates the length of s, a la strlen. It first assigns the address of s to t and then uses pointer arithmetic to look for, one char at a time, the trailing NUL character. It then subtracts s from t in order to count the number of chars in between.
  1. This function returns \(x^y\), a la pow. It first initializes n to 1, thereafter multiplying n by x a total of y times, effectively computing x to the power of y.
  1. This function converts a number, represented as a string, to an int, a la atoi. It does so by iterating over every digit in s, from right to left, converting each char to an equivalent int (by subtracting from each the ASCII value of 0), thereafter multiplying the result by a power of 10 according to its place in s. 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

  1. 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';
    }
    
  1. 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);
    }
    
  1. 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

  1. 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.
  1. 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.
  1. 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.
  1. 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

  1. A user could simply change the value of vip from 0 to 1, as via their browser’s developer tools, and then submit the form without moderation.
  1. document.querySelector('form').addEventListener('submit', function(e) {
        let content = document.querySelector('#content').value;
        if (content.toLowerCase().includes('vaccine') && !vip) {
            e.preventDefault();
        }
    });
    
  1. covid, covid-19, vaccine, vaccinate, vaccinated, vaccination, and vaccinations.
  1. A user could simply change the value of vip from false to true 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.
  1. This implementation would prevent users who aren’t VIPs from even mentioning vaccine (or, with the regex, related terms), even to communicate accurate information.
  1. def is_vip(username):
        rows = db.execute("SELECT vip FROM users WHERE username = ? AND vip = 1", username)
        return len(rows) == 1
    
  1. UPDATE users SET vip = 0;
    
  1. Answers vary.
  1. Answers vary.