CS 291 Assignment #2

Due Monday, February 9th (by 11:59pm)

Introduction:

This time around you'll practice with tuples, list comprehensions, and higher-order functions. The last problem will give you a chance to work on solving a problem that requires "gluing together" multiple steps. Style matters on this assignment: Try to be as short and concise as possible in your solutions, use pattern-matching when you can, and make an effort to take advantage of built-in functions as much as possible. Make sure you read the section on submitting before you turn in your assignment, as I've changed some of the details from last time (including a request that you submit a script file showing your output in Hugs). Enjoy!

The Assignment

  1. Define the function tuples_summing_to_zero that takes a list of two-tuples as input and returns those tuples from the input list whose values sum to zero. The tuples in the output list should appear in the same order as they did in the input list. For full credit, use a list comprehension in your solution.
    > tuples_summing_to_zero []
    []
    > tuples_summing_to_zero [(1,0), (0,-1)]
    []
    > tuples_summing_to_zero [(-1,-2), (0,0), (2,-1), (-2,2)]
    [(0,0),(-2,2)] 
    > :type tuples_summing_to_zero
    tuples_summing_to_zero :: Num a => [(a,a)] -> [(a,a)]
    

  2. Write a function average_dist that takes a list of Cartesian coordinates (two-tuples) and computes the average distance from the origin to each point in the input list that lies in the first quadrant. (Points whose X and Y coordinates are both positive are in the first quadrant.) You may assume that at least one such point is in the input list. For full credit, use a list comprehension in your solution and avoid redundant computation by using let or where.
    > average_dist [(1,1)]
    1.41421
    > average_dist [(-2,1),(1,1),(2,-3),(0,0)]
    1.41421
    > average_dist [(2,2), (-2,2), (3,3)]
    3.53553
    >:type average_dist
    average_dist :: (Ord a, Floating a) => [(a,a)] -> a
    
  3. In the next problem, you'll write a higher-order function that performs numerical integration. One of the inputs to this function is a function that takes as inputs two Y-coordinates and the distance between them along the X-axis. It returns the approximate area under the curve that connects the Y-coordinates. Here, you'll write two different approximation functions that can be plugged in later.

    1. Write a function area_trap that uses the trapezoid rule to approximate the area. (i.e. "connect the dots")

    2. Write a function area_rect that approximates the area with a rectangle whose height is equal to the first Y-coordinate.

  4. In your script file, show that these functions work.

  5. Write a function integrate with a type at least as general as: (Num a, Ord b, Num b) => (b -> c -> c -> a) -> b -> b -> b -> (b -> c) -> a. (Whew!) The first input to integrate is an approximation function like the ones from the previous problem. (That's the "(b -> c -> c -> a)" component of the type signature.) The next three arguments are the spacing between evaluation points and the starting and ending X-coordinates, respectively. (The "b -> b -> b" in the type.) The last argument is the function to be integrated. (The "(b -> c)" in the type.)
    > integrate area_trap 0.1 0 100 (\x->x*x)    
    333333.500000013
    > integrate area_rect 0.1 0 100 (\x->x*x)
    332833.500000013
    > integrate area_trap 0.3 0 1 (\x->x)
    0.5
    > :type integrate
    integrate :: (Num a, Ord b, Num b) => (b -> c -> c -> a) -> b -> b -> b -> (b -> c) -> a
    

  6. Define a function trap_int that performs numerical integration using the trapezoid method with a spacing of 0.1 between evaluation points. It takes three inputs: the starting and ending X-coordinates and a function to be integrated. For full credit, define trap_int using partial application of integrate.
    > trap_int 0 100 (\x->x*x)
    333333.500000013
    > trap_int 0 10 (\x->x)
    50.0
    > :type trap_int
    trap_int :: Double -> Double -> (Double -> Double) -> Double
    

  7. Define a function most_frequent that returns the item that occurs most frequently in an input list. (In the case of a tie, it doesn't matter which you return.) Try to use built-in list operations as much as possible to reduce the amount of code you have to write.
    > most_frequent []
    
    Program error: Not defined on empty lists
    
    > most_frequent [1,2]
    1
    > most_frequent ['b','a','c','a','d']
    'a'
    

Submitting:

Submit both the file containing your function definitions, and a script file of a Hugs98 session showing the evaluation of the sample inputs given in each problem above. (Feel free to include additional tests if you wish.) Please name both files after yourself (e.g. "richards.hs" and "richards_out.txt"). Submit by attaching your files to an E-mail to me at brichards@ups.edu. Please do not just copy and paste your solutions into the body of the E-mail!


Brad Richards, 2009