Disclaimer: This was done quickly, please be vigilant for errors, wrong answers, and bad reasoning. If you find any of these please message me!

1 - Theory

Break it into parts, what does the process_digits() function do, and what does the main() function do?

The process_digits() function returns the highest digit in an input number. The main() function prints the process_digits() return value for the number 234, combining these we get: Prints the highest digit in the number 234. Which is close enough to the model answer.

2 - Theory

Lets start with the 'something' variable, if we know what that is we can figure out what the 'xxxx' variable is, and then finally get a proper name for the 'who_knows()' function.

Note how the function does a 'for ... in range(len(something))' loop, so 'something' must be a list.
The if statement, if a_thing < 0, is also very helpful, this numerical comparison means something[xxxx] must be a number of some sort, and since 'xxxx' is in square brackets it must be the index of an item in the 'something' list.
We can now safely call 'something' numbers_list, and 'xxxx' can be number.

Now look at what the function is doing, which is popping/removing the number from the numbers_list if its below 0, aka negative, in other words, it is removing negative numbers from the list.

3 - Theory

This question is testing knowledge on how lists work.
When the do_something() function assigns list2 to list1, you can think of it as list1 having an alternate name, so when the function later appends to list2, it is really just appending to list1.

Because of this, list1 (which is a_list in the main() function), becomes [1, 4, 3, 2, 1, 4]

4 - Theory

This question is testing knowledge on how scope works.
Using our knowledge from the last question we know that list1 (a_list in the main() function) has the value [3, 7, 2, 5] after the appending the do_something2() function does.
However the place where most people trip-up on this is the next line, list1 = list2. While in the scope of the do_something2() function, it is true the value of list1 points to list2, [4, 3], once we "leave" the do_something2() function and go back into the main() function, list2 doesn't exist anymore, and so list1 remains as [3, 7, 2, 5]

5 - Theory

The format for these style of questions is just 1 line, no if statement, no return True, just the boolean expression you would normally put in an if statement.

Exactly between 2 and 12 (inclusive) = greater than or equal to 2 and less than or equal to 12 = value >= 2 and value <= 12.

6 - Theory

Exactly divisible by 13 = value % 13 == 0
Not visible by 5 = value % 5 != 0
Combined: value % 13 == 0 and value % 5 != 0

7 - Theory

Remember the format of a doctest, a doctstring (""") in the thing you want to test, three > symbols and then the test itself, and then the expected output on the next line.
For the swap_halves() function, we need to make a test it passes and a test it fails, the latter can be accomplished by 'expecting' an incorrect output.

        >>> swap_halves([0, 1])
        [1, 0]
        >>> swap_halves([1, 2, 4, 5])
        [5, 4, 1, 2]

The first test with [0, 1] passes, since the returned [1, 0] from the swap_halves() function matches what we expected. However the second test fails, because even though the swap_halves() function correctly swapped the numbers we specified, we expected a wrong output on purpose.

8 - Programming

This question has the unfortunate bug of the second input, SpentSoFar2.txt, having erroneous newlines at the end of its contents, to get rid of these we can add a while loop to filter them out.

        def read_from_file(filename):
            input_file = open(filename, 'r')
            contents = input_file.read().split('\n')
            while contents[-1] == "":
            return contents

9 - Programming

No errors here luckily, only note is that the spaces between the item category and its amount spent are not equal, so instead of doing .find() on each item, its easier to just .split() and get the first and last item of the list that creates.

        def get_total_amount_spent(item_list, category):
            total = 0
            for item in item_list:
                if item.split()[0] == category:
                    total += int(item.split()[-1])
            return total

10 - Programming

This one is a bit easier than the previous questions in my opinion, just note that the index of the category in the items_of_interest list == the index of that category's price in the spent_each_item list.

        def write_to_file(items_of_interest, spent_each_item):
            total = 0
            output_file = open('ntoa222.txt', 'w')
            for i in range(len(items_of_interest)):
                output_file.write(str(i + 1) + ". " + items_of_interest[i] + " $" + str(spent_each_item[i]) + '\n')
                total += spent_each_item[i]
            output_file.write('\nTotal: $' + str(total))

The 'str(i + 1)' part is a little hack of making the written list numbered.

11 - Programming

First loop through each key in dict1, and if that key is also in dict2, make dict3's value for that key be the maximum of dict1 and dict2's values for that key.

        def get_max_dict(dict1, dict2):
            dict3 = {}
            for key in dict1:
                if key in dict2:
                    dict3[key] = max(dict1[key], dict2[key])
            return dict3

12 - Programming

Another relatively easy one, just make sure you're accounting for uppercase vowels, and only adding the vowels score if it's not in the special_letters dictionary (aka elif instead of else or if).

        def get_text_value(special_letters, text):
            valuation = 0
            vowels = "aeiou"
            for char in text.lower():
                if char in special_letters:
                    valuation += special_letters[char]
                elif char in vowels:
                    valuation += 1
            return valuation

13 - Programming

Who doesn't love GUI?
Instead of overcomplicating things by having a second, nested loop for printing column by column, lets stick to using 1 loop and printing row by row, meaning we will print 3 squares (or 'rectangles') per row, for 5 rows total.
Lets also define a starting x and y coodinate, and increment this y coordinate every row.

        def draw_pattern(a_canvas, size):
            start_x = 10
            start_y = 10
            for i in range(5):
                # canvas drawing
                start_y += size

Since the starting x coordinate of the row depends on the row number, lets add that in to the loop as well, accounting for odd row numbers (1 and 3) are offset 1 'size' to the right.

        def draw_pattern(a_canvas, size):
            start_x = 10
            start_y = 10
            for i in range(5):
                x = start_x
                if i % 2 == 1:
                    x += size
                # canvas drawing
                start_y += size

Now we just print the 3 rectangles, with the second and third ones being 3 sizes to the right of the previous.

        def draw_pattern(a_canvas, size):
            start_x = 10
            start_y = 10
            for i in range(5):
                x = start_x
                if i % 2 == 1:
                    x += size
                a_canvas.create_rectangle(x, start_y, x + size, start_y + size, fill='blue')
                x += size * 3
                a_canvas.create_rectangle(x, start_y, x + size, start_y + size, fill='blue')
                x += size * 3
                a_canvas.create_rectangle(x, start_y, x + size, start_y + size, fill='blue')
                start_y += size
Back to 101 Index