Cornell University 12 Oct Solutions. (a) [9 pts] For each of the 3 functions below, pick an appropriate type for it from the list below.

Similar documents
Homework 3 COSE212, Fall 2018

Recap from last time. Programming Languages. CSE 130 : Fall Lecture 3: Data Types. Put it together: a filter function

Mini-ML. CS 502 Lecture 2 8/28/08

Inductive Data Types

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

Programming Languages

15 150: Principles of Functional Programming Sorting Integer Lists

Preliminary Examination I Computer Science 312, Cornell University 6 March 2003

Lists. Michael P. Fourman. February 2, 2010

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

Fall 2018 Lecture N

Recap: ML s Holy Trinity

Fall Recursion and induction. Stephen Brookes. Lecture 4

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

GADTs. Wouter Swierstra. Advanced functional programming - Lecture 7. Faculty of Science Information and Computing Sciences

Modules and Representation Invariants

Chapter 3 Linear Structures: Lists

OCaml. ML Flow. Complex types: Lists. Complex types: Lists. The PL for the discerning hacker. All elements must have same type.

Recap: ML s Holy Trinity. Story So Far... CSE 130 Programming Languages. Datatypes. A function is a value! Next: functions, but remember.

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

CSE 130 Programming Languages. Datatypes. Ranjit Jhala UC San Diego

Chapter 3 Linear Structures: Lists

Solutions to the Second Midterm Exam

CSE 130 Programming Languages. Lecture 3: Datatypes. Ranjit Jhala UC San Diego

Recursive Definitions Structural Induction Recursive Algorithms

Fall Lecture 3 September 4. Stephen Brookes

General Computer Science (CH ) Fall 2016 SML Tutorial: Practice Problems

CSE341 Autumn 2017, Midterm Examination October 30, 2017

15 212: Principles of Programming. Some Notes on Induction

COMPUTER SCIENCE TRIPOS

CMSC 330: Organization of Programming Languages. Formal Semantics of a Prog. Lang. Specifying Syntax, Semantics

Functional Programming Mid-term exam Tuesday 3/10/2017

Foundations of Computation

CS 321 Programming Languages

CSE-321 Programming Languages 2012 Midterm

Exercise 1 ( = 24 points)

News. Programming Languages. Recap. Recap: Environments. Functions. of functions: Closures. CSE 130 : Fall Lecture 5: Functions and Datatypes

Haskell Overview II (2A) Young Won Lim 8/23/16

MoreIntro.v. MoreIntro.v. Printed by Zach Tatlock. Oct 07, 16 18:11 Page 1/10. Oct 07, 16 18:11 Page 2/10. Monday October 10, 2016 lec02/moreintro.

CSc 372 Comparative Programming Languages

Australian researchers develop typeface they say can boost memory, that could help students cramming for exams.

Recursion defining an object (or function, algorithm, etc.) in terms of itself. Recursion can be used to define sequences

CSE-321 Programming Languages 2010 Midterm

Sample Exam; Solutions

Handout 2 August 25, 2008

15 210: Parallel and Sequential Data Structures and Algorithms

CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

Plan (next 4 weeks) 1. Fast forward. 2. Rewind. 3. Slow motion. Rapid introduction to what s in OCaml. Go over the pieces individually

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

Exercise 1 (2+2+2 points)

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

GADTs. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 7. [Faculty of Science Information and Computing Sciences]

Lecture Notes on Induction and Recursion

CSE 341 Section 5. Winter 2018

Lists. Adrian Groza. Department of Computer Science Technical University of Cluj-Napoca

Introduction to Programming, Aug-Dec 2006

Induction in Coq. Nate Foster Spring 2018

CSE3322 Programming Languages and Implementation

GADTs. Alejandro Serrano. AFP Summer School. [Faculty of Science Information and Computing Sciences]

Standard ML. Data types. ML Datatypes.1

Exercise 1 ( = 22 points)

Math 454 Final Exam, Fall 2005

Introduction to Typed Racket. The plan: Racket Crash Course Typed Racket and PL Racket Differences with the text Some PL Racket Examples

Programming Paradigms

F# - LISTS. In this method, you just specify a semicolon-delimited sequence of values in square brackets. For example

The type checker will complain that the two branches have different types, one is string and the other is int

Logic - CM0845 Introduction to Haskell

CSE 341 : Programming Languages Midterm, Spring 2015

Functional Programming

Structure and Interpretation of Computer Programs

News. Programming Languages. Complex types: Lists. Recap: ML s Holy Trinity. CSE 130: Spring 2012

Type Checking and Type Inference

Lecture 4: Higher Order Functions

PROGRAMMING IN HASKELL. CS Chapter 6 - Recursive Functions

Recursively Defined Functions

Lecture 3: Recursion; Structural Induction

Tuples. CMSC 330: Organization of Programming Languages. Examples With Tuples. Another Example

CSCE 314 Programming Languages

MoreIntro_annotated.v. MoreIntro_annotated.v. Printed by Zach Tatlock. Oct 04, 16 21:55 Page 1/10

CIS 500 Software Foundations. Midterm I. (Standard and advanced versions together) October 1, 2013 Answer key

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

CS115 - Module 10 - General Trees

Shell CSCE 314 TAMU. Higher Order Functions

Complexity, Induction, and Recurrence Relations. CSE 373 Help Session 4/7/2016

(a) (4 pts) Prove that if a and b are rational, then ab is rational. Since a and b are rational they can be written as the ratio of integers a 1

SML A F unctional Functional Language Language Lecture 19

Problem 1. (20pts) Parser Technology a) Look again at our grammar for well- matched bracket sequences:

Analyze the obvious algorithm, 5 points Here is the most obvious algorithm for this problem: (LastLargerElement[A[1..n]:

Programming in Standard ML: Continued

Advanced Programming Handout 3

Review. Advanced Programming Handout 3. Review. Review. Review. Trees. What are the types of these functions? How about these? f1 x y = [x] : [y]

9/23/2014. Function: it s easy and it is fun Local Function & Composite Function Polymorphic function I/O Structure and signature

CS 320: Concepts of Programming Languages

An introduction introduction to functional functional programming programming using usin Haskell

F28PL1 Programming Languages. Lecture 14: Standard ML 4

Introduction to SML Basic Types, Tuples, Lists, Trees and Higher-Order Functions

Type families and data kinds

Haskell Overview II (2A) Young Won Lim 8/9/16

Problem Set CVO 103, Spring 2018

Transcription:

Cornell University 12 Oct 2006 Solutions 1. Types, Polymorphism [14 pts] (parts a b) (a) [9 pts] For each of the 3 functions below, pick an appropriate type for it from the list below. i. fun f x y = (y, x) (B) a -> b -> ( b * a). ii. fun f (x, y) z = z y (D) ( a * b) -> ( b -> c) -> c. iii. fun f x y = fn y => (y, x) (G) a -> b -> c -> ( c * a) A. ( a * b) -> c -> b B. a -> b -> ( b * a) C. ( a * b) -> ( b * a) D. ( a * b) -> ( b -> c) -> c E. a -> b -> c -> ( b * a) F. ( a * b) -> c -> c * b G. a -> b -> c -> ( c * a) (b) [5 pts] Write a datatype declaration that describes a list structure with elements of alternating types. That is, odd elements have some type a, and even elements have some type b. datatype ( a, b) list = Nil Cons of a * ( b, a) list 2. Pattern matching [18 pts] (parts a b) (a) [8 pts] The following datatype describes syntax trees for arithmetic expressions: 1

datatype expr = Const of int Plus of expr * expr Times of expr * expr Use pattern matching to implement a function trans: expr -> expr that transforms an expression e into an equivalent expression by distributing multiplication over addition for all subexpression of e. Make sure you identify all cases where this transformation is applicable. fun trans(e: expr): expr = case e of Times(e1, Plus(e2,e3)) => Plus(Times(trans e1, trans e2), Times(trans e1, trans e3)) Times(Plus(e1,e2), e3) => Plus(Times(trans e1, trans e3), Times(trans e2, trans e3)) _ => e (b) [10 pts] Write a function zip : int list * int list -> int list combines two lists a and b by inserting the i-th element of a before the 2i-th element of b. If list b is too short, excess elements are appended. For example: zip([1, 2, 3, 4], [11, 12, 13]) = [1, 11, 12, 2, 13, 3, 4] fun zip(a: int list, b: int list): int list = case (a, b) of (x::tx, y::y ::ty) => x::y::y ::zip(tx, ty) (x::tx, [y]) => x::y::tx (_, []) => a ([], _) => b 3. Using fold functions [20 pts] (parts a c) Absolute frequency distributions are obtained by dividing a data set into several classes and then counting the number of elements in each class. For example, an absolute frequency distribution for student grades in this exam can be constructed by considering the grade ranges (0-10),.., (80-90), (90-100), and counting the number of students in each range. We ll represent frequency distributions as lists of integers. A histogram is a graphical representation of a frequency distribution graphically, as a sequence of vertical bars. The height of each bar indicates the frequency at that point. We want to write a function histogram that prints out a histogram in text form. For instance, histogram([3,1,2] must produce the following output: 2

* * * *** Below is a sketch of the code for this function. The function assumes that each element in the input list is non-negative. fun histogram(dist: int list): unit = let val num: int =... fun line(i: int): string =... fun show(i: int): string = if i = 0 then "" else (line i) ^ "\n" ^ (show(i-1)) in print (show num) end The code for num and line can be implemented concisely using list folding operations. Recall the following definition: fun foldl f v l = case l of nil => v h::t => foldl f (f(h,v)) t (a) [6 pts] Write the appropriate code for num using foldl. val num: int = foldl Int.max 0 dist (b) [6 pts] Write function line using list folding. fun line(i: int): string = foldl (fn (x,a) => a^(if x < i then " " else "*")) "" dist (c) [8 pts] A cumulative distribution is similar to an absolute frequency distribution, but for each range it counts the elements in that range, plus all elements in the smaller ranges. Write a function cumulative that converts an absolute frequency distribution into a cumulative distribution. For instance: cumulative([3,1,2])=[3,4,6]. Implement this function using foldl. Make sure that elements in your result are properly ordered. fun cumulative(dist: int list): int list = rev( #2( foldl (fn(x,(y,z)) => (x+y,x+y::z)) (0,[]) dist ) ) 3

4. Data Abstraction [18 pts] (parts a b) The following signature models sets of integers: signature INTSET = sig (* A "set" is a set of integer values *) type set (* The empty set *) val empty: set (* insert(n, s) adds integer n to set s *) val insert: int * set -> set (* remove(n, s) deletes integer n from set s *) val remove: int * set -> set (* equal(s,t) is true if sets s and t contain the same values *) val equal: set * set -> bool end For sets that contain many consecutive numbers, it is more efficient to use value ranges, rather than enumerating all values. It is appropriate to represent such sets as lists of pairs, where each pair denotes an integer range: type set = (int * int) list In addition, we want to implement set equality in a straightforward manner: val equal(s: set, t: set): bool = s = t (a) [6 pts] Define an appropriate representation invariant that would make the above implementation of equal correct. A list [(a 0, a 1 ), (a 2, a 3 ),.., (a 2n, a 2n+1 )] must be such that: All ranges are valid: a 2i a 2i+1, for all i All ranges are disjoint, not adjacent, and in increasing order: a 2i+1 a 2i+2 2 for all i The representation invariant ensures that each set has a unique implementation. Therefore, set equality via list equality is correct. 4

(b) [12 pts] Finish the implementation below for function remove, by filling in the inner case statement. Do not use other if or case statements in the remaining of the code. You may find it helpful to use the function Int.compare: int * int -> order to compare two integers and obtain their ordering: LESS, EQUAL, or GREATER. You must ensure that your code maintains the representation invariant. fun remove(n: int, s: set): set = case s of nil => nil (a,b)::t => case (Int.compare(n,a), Int.compare(n,b)) of (LESS, _) => s (EQUAL, EQUAL) => t (EQUAL, _) => (a+1,b)::t (_, EQUAL) => (a,b-1)::t (_,LESS) => (a,n-1)::(n+1,b)::t _ => (a,b)::remove(n,t) 5. Complexity [20 pts] (parts a c) Consider the following implementation of list reversal: fun reverse(l: int list): int list = case l of nil => nil [x] => [x] _ => let val n = List.length(l) div 2 val x = List.take(l, n) val y = List.drop(l, n) in (reverse y) @ (reverse x) end The complexity of an append operation a @ b is O(n) in the length of the first list a. Function List.length is O(n) where n in the length of its input list. Function List.take(l,n) returns the first n elements of list l, and List.drop(l,n) returns the remaining elements. Both of these functions are O(n) where n is their integer argument. (a) [5 pts] Write a recurrence for the running time of reverse. 5

T(0) = c 1 T(1) = c 2 T(n) = 2T(n/2) + c 3 n + c 4, for n > 1 (b) [10 pts] What is the complexity of reverse? Prove your answer. The complexity is O(n log n). Take c 1 = c 2 = c 3 = 1. Ignore c 4 because it is subsumed by c 3 n. Therefore: T(0) = T(1) = 1 T(n) = 2T(n/2) + n, for n > 1 We show that T(n) n + n log n, for all n >= 1, using strong induction on n. Induction statement. P(n) = T(n) n + n log n. Base case n = 1. T(1) = 1 = 1 + 1log1. Induction Hypothesis. Assume that T(k) k + k log k, for all k = 0,.., n for some n > 1. Induction Step. Prove that T(n + 1)leq(n + 1) + (n + 1) log(n + 1). We have : T(n + 1) = 2T((n + 1)/2) + (n + 1) (because n > 1) 2((n + 1)/2 log((n + 1)/2) + (n + 1)/2) + (n + 1) (by IH, because (n + 1)/2 n) = (n + 1) log((n + 1)/2) + 2(n + 1) = (n + 1) log(n + 1) This completes the proof. Hence T(n) n + n log n, so T(n) is O(n log n). (c) [5 pts] Write a list reversal function reverse2 that runs faster than reverse for large lists. Needless to say, List.rev is not accepted as an answer. val reverse2 l = foldl List.:: nil l 6. Evaluation [10 pts] Consider the following function: fun foo (n: int) (f: int->int): int = if n < 3 then f(n) else foo (n-1) (fn m => f(n * m)) (a) [7 pts] Write the evaluation of expression foo 3 (fn x=>x+1). Write your solution using reductions of the form e -> e. You may find it useful to name function values and use their names during evaluation. Here is an example of an evaluation using reductions: 6

(fn x => fn y => y x) 2 (fn x => x) -> (fn y => y 2) id [where id = fn x => x] -> id 2 -> 2 foo 3 (fn x => x) -> (fn f => if 3 < 3 then f(3) else foo (3-1) (fn m => f(3 * m))) f1 [where f1 = fn x => x+1] -> if 3 < 3 then f1(3) else foo (3-1) (fn m => f1(3 * m)) -> if false then f1(3) else foo (3-1) f2 [where f2 = fn m => f1(3 * m)] -> foo (3-1) f2 -> foo 2 f2 -> (fn f => if 2 < 3 then f(2) else foo (2-1) (fn m => f(2 * m))) f2 -> if 2 < 3 then f2(2) else foo (2-1) (fn m => f2(2 * m)) -> if true then f2(2) else foo (2-1) f3 [where f3 = fn m => f2(2 * m)] -> f2(2) -> f1(3 * 2) -> f1(6) -> 7 (b) [3 pts] Given a number n > 0 and and arbitrary function f, what does the expression foo n f compute? It computes f(n!) 7