2025-11-06

  1. [2pts*] Translate the following into first order logic:

    i. Every student in this class has submitted at least one assignment. - S(x): “x is a student in this class” - A(x, y): “x has submitted assignment y”

    \[\forall x (S(x) \to \exists y A(x,y))\]

    ii. There is a professor who teaches every student in this class. - P(x): “x is a professor” - S(y): “y is a student in this class” - T(x, y): “x teaches y”

    \[\exists x (P(x) \land \forall y (S(y) \to T(x,y)))\]
  2. [1pt] Complete the missing parts of the following function:
     def sum_naturals(n):
         """Return the sum of the first n natural numbers."""
         total, k = 0, 1
         while k <= n:
             # Your code here
             total, k = total + k, k + 1
             # End of your code
         return total
    
  3. [2pts*] Simplify the function seclarge as much as you can by making use of the function max. Remember that max takes two numbers as arguments and returns the larger one.

    Here is one way to do it:
     def seclarge(x, y, z):
         """Return the second largest of three numbers."""
    
         if x >= max(y,z):
             return max(y, z)
         elif y >= max(x,z):
             return max(x,z)
         elif z >= max(x,y):
             return max(x,y)
    

    First, note the switch from > to >=. Without it there will be incorrect output for certain cases, can you see which?

    Second, we can further simplify our function. Do we need the check z >= max(x,y)? Think a little before reading on.


    We actually don’t. At the point control reaches the second elif in the above code, we already know that x is less than y, or z or both. We also know that y is less than z, because if it were not, it should have been greater than or equal to the maximum of z and x. Therefore, we can safely say that z is the largest of the three. All we need at that point is to return the maximum of x and y. Here is the code:

     def seclarge2(x, y, z):
         """Return the second largest of three numbers."""
    
         if x > max(y,z):
             return max(y, z)
         elif y > max(x,z):
             return max(x, z)
         else:
             return max(x, y)
    

    Also note that we can switch back to > from >= with this solution.

    There is still room for improvement in our function. We compute max(y,z) and max(x,z) twice each in the above code. We can store them in variables to avoid recomputing them. Here is the final code:

     def seclarge3(x, y, z):
         """Return the second largest of three numbers."""
         yz = max(y,z)
         xz = max(x,z)
         if x > yz:
             return yz
         elif y > xz:
             return xz
         else:
             return max(x,y)
    

    Can you think of any further improvements? Is there a version that makes fewer comparisons?