Madhavan Mukund



Programming and Data Structures with Python
Aug–Nov 2024

Practice Assignment 2

2 September, 2024


Write Python functions as specified below.

  • You may define additional auxiliary functions as needed.
  • In all cases you may assume that the value passed to the function is of the expected type, so your function does not have to check for malformed inputs.

Problems

  1. Function: threesquares(m)

    A positive integer m can be expresseed as the sum of three squares if it is of the form p + q + r where p, q, r ≥ 0, and p, q, r are all perfect squares. For instance, 2 can be written as 0+1+1 but 7 cannot be expressed as the sum of three squares. The first numbers that cannot be expressed as the sum of three squares are 7, 15, 23, 28, 31, 39, 47, 55, 60, 63, 71, … (see Legendre's three-square theorem).

    Write a Python function threesquares(m) that takes an integer m as input and returns True if m can be expressed as the sum of three squares and False otherwise. (If m is not positive, your function should return False.)

    Here are some examples of how your function should work.

    	  >>> threesquares(6)
    	  True
    
    	  >>> threesquares(188)
    	  False
    
    	  >>> threesquares(1000)
    	  True
    	
  2. Function: hillvalley(l)

    A list of numbers is said to be a hill if it consists of an ascending sequence followed by a descending sequence, where each of the sequences is of length at least two. Similarly, a list of numbers is said to be a valley if it consists of an descending sequence followed by an ascending sequence. You can assume that consecutive numbers in the input sequence are always different from each other.

    Write a Python function hillvalley(l) that takes a list l of integers and returns True if it is a hill or a valley, and False otherwise.

    Here are some examples to show how your function should work.

    	  >>> hillvalley([1,2,3,5,4])
    	  True
    
    	  >>> hillvalley([1,2,3,4,5])
    	  False
    
    	  >>> hillvalley([5,4,1,2,3])
    	  True
    
    	  >>> hillvalley([5,4,3,2,1])
    	  False
    	
  3. Function: shuffle(l1,l2)

    Write a function shuffle(l1,l2) that takes as input two lists, 11 and l2, and returns a list consisting of the first element in l1, then the first element in l2, then the second element in l1, then the second element in l2, and so on. If the two lists are not of equal length, the remaining elements of the longer list are appended at the end of the shuffled output.

    Here are some examples to show how your function should work.

     
    	  >>> shuffle([0,2,4],[1,3,5])
    	  [0, 1, 2, 3, 4, 5]
    
    	  >>> shuffle([0,2,4],[1])
    	  [0, 1, 2, 4]
    
    	  >>> shuffle([0],[1,3,5])
    	  [0, 1, 3, 5]
    	
  4. Function: duplicates(l)

    Write a function duplicates(l) that finds all duplicate values in l. Your function should retain the first copy of each duplicate value — in other words, you should preserve the order in which values appear in l.

    Duplicates could be simple values such as numbers or complex values such as strings and lists. You need to find duplicates only at the top level of the list – if a list contains another list or string as an element with duplicate values, the nested list or string can remain as it is.

    Your function should return a new list of duplicates. It should not modify the input list l.

    Here are some examples to show how your function should work.

     
    	  >>> duplicates([7,2,5,7,2,9])
    	  [7, 2]
    
    	  >>> duplicates([7,2,"hello",2,[5,5],"hello",9,[5,5]])
    	  [2, 'hello', [5, 5]]
    	
  5. Function: splitwith(l,x)

    Write a function splitwith(l,x) that uses x as a separator to split the list l into sublists. Your function should return the list of sublists generated by splitting l in this way: all occurrences of x should be omitted. In other words, if your function returns the list of lists [l1,l2,…,lk] then it should be the case that

    l == l1 + [x] + l2 + [x] + ... + [x] + lk

    • If there is no occurrence of x in l, the value returned should be list consisting of a single inner list which is the entire input list l.

    • If x occurs at the first/last position of the list, one of the sublists (before/after x, respectively) will be the empty list.

    • Likewise, if there are two consecutive occurrences of x in l, they will be separated by the empty list.

    Here are some examples to show how your function should work.

     
    	  >>> splitwith([7,2,5,7,7,[2,7],9],7)
    	  [[], [2, 5], [], [[2, 7], 9]]
    	  
    	  >>> splitwith([7,2,5,7,[2,7],9],8)
    	  [[7, 2, 5, 7, [2, 7], 9]]
    
    	  >>> splitwith([7,2,[8],8,[8],[[8],7],2,9],[8])
    	  [[7, 2], [8], [[[8], 7], 2, 9]]
    
    	  >>> splitwith([1,2,1],1)
    	  [[], [2], []]