Lab 10: OCaml sequences, comparators, stable sorting 12:00 PM, Nov 12, 2017

Similar documents
Lab 7: OCaml 12:00 PM, Oct 22, 2017

Homework 8: Matrices Due: 11:59 PM, Oct 30, 2018

Lecture 27: (PROVISIONAL) Insertion Sort, Selection Sort, and Merge Sort 10:00 AM, Nov 8, 2017

The Design Recipe Fall 2017

The Design Recipe Fall 2018

(Provisional) Lecture 22: Rackette Overview, Binary Tree Analysis 10:00 AM, Oct 27, 2017

(Provisional) Lecture 08: List recursion and recursive diagrams 10:00 AM, Sep 22, 2017

(Provisional) Lecture 20: OCaml Fun!

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

Racket Style Guide Fall 2017

(Provisional) Lecture 32: Estimated Value, Minimax, Functional Data 10:00 AM, Nov 20, 2017

Intro. Scheme Basics. scm> 5 5. scm>

Homework 7: Subsets Due: 11:59 PM, Oct 23, 2018

Homework 6: Higher-Order Procedures Due: 10:00 PM, Oct 17, 2017

List Functions, and Higher-Order Functions

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)

Homework 6: Higher-Order Procedures Due: 11:59 PM, Oct 16, 2018

Lab 9: More Sorting Algorithms 12:00 PM, Mar 21, 2018

Lecture: Functional Programming

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

Homework 3: Recursion Due: 11:59 PM, Sep 25, 2018

Thinking Induc,vely. COS 326 David Walker Princeton University

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

Homework 12: Tail Recursion and Analysis Due: 11:59 PM, Dec 4, 2018

OCaml Style Guide Fall 2017

CSE 341, Autumn 2005, Assignment 3 ML - MiniML Interpreter

Programming Languages and Techniques (CIS120)

Dialects of ML. CMSC 330: Organization of Programming Languages. Dialects of ML (cont.) Features of ML. Functional Languages. Features of ML (cont.

Lab 2: Object-Oriented Design 12:00 PM, Jan 31, 2018

Background. CMSC 330: Organization of Programming Languages. Useful Information on OCaml language. Dialects of ML. ML (Meta Language) Standard ML

Introduction to Programming, Aug-Dec 2006

Lecture 5: Implementing Lists, Version 1

Lecture 6: Sequential Sorting

Lab 1: Setup 12:00 PM, Sep 10, 2017

Functional Programming. Pure Functional Programming

Text Input and Conditionals

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Working with recursion. From definition to template. Readings: HtDP, sections 11, 12, 13 (Intermezzo 2).

Working with recursion

SOFTWARE ENGINEERING DESIGN I

CMSC 330: Organization of Programming Languages. Operational Semantics

PROBLEM SOLVING 11. July 24, 2012

Lab 4: Imperative & Debugging 12:00 PM, Feb 14, 2018

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #29 Arrays in C

LAB 5, THE HIDDEN DELIGHTS OF LINKED LISTS

CMSC 201 Fall 2016 Lab 09 Advanced Debugging

Functional Programming. Introduction To Cool

1 ICS 161: Design and Analysis of Algorithms Lecture notes for January 23, Bucket Sorting

OCaml Data CMSC 330: Organization of Programming Languages. User Defined Types. Variation: Shapes in Java

Homework 2: Imperative Due: 5:00 PM, Feb 15, 2019

MP 3 A Lexer for MiniJava

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

Burning CDs in Windows XP

Programming Assignment: recursion, recursion, recursion Due date: Thursday, July 26 at 11:29 am

Algebraic Specifications

Case by Case. Chapter 3

Lecture 7: Lists, Version 2 (with Mutation)

COMP 105 Homework: Type Systems

Recap. Recap. If-then-else expressions. If-then-else expressions. If-then-else expressions. If-then-else expressions

Programming Languages and Techniques (CIS120)

RACKET BASICS, ORDER OF EVALUATION, RECURSION 1

CS558 Programming Languages

Lecture Programming in C++ PART 1. By Assistant Professor Dr. Ali Kattan

Programming Languages

Learning Recursion. Recursion [ Why is it important?] ~7 easy marks in Exam Paper. Step 1. Understand Code. Step 2. Understand Execution

Statistics Case Study 2000 M. J. Clancy and M. C. Linn

Lab 5: Java IO 12:00 PM, Feb 21, 2018

Testing. UW CSE 160 Winter 2016

Lab 8: Introduction to Scala 12:00 PM, Mar 14, 2018

Scheme: Data. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, April 3, Glenn G.

Introduction to OCaml

CS109A ML Notes for the Week of 1/16/96. Using ML. ML can be used as an interactive language. We. shall use a version running under UNIX, called

Lab 10: Sockets 12:00 PM, Apr 4, 2018

Lecture 31: Graph Search & Game 10:00 AM, Nov 16, 2018

COSE212: Programming Languages. Lecture 4 Recursive and Higher-Order Programming

Python allows variables to hold string values, just like any other type (Boolean, int, float). So, the following assignment statements are valid:

Python lab session 1

CS1 Lecture 3 Jan. 22, 2018

MP 3 A Lexer for MiniJava

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

A First Look at ML. Chapter Five Modern Programming Languages, 2nd ed. 1

If Statements, For Loops, Functions

Exam Datastrukturer. DIT960 / DIT961, VT-18 Göteborgs Universitet, CSE

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #06 Loops: Operators

Difference Between Dates Case Study 2002 M. J. Clancy and M. C. Linn

CMPSCI 187 / Spring 2015 Sorting Kata

Hints for Exercise 4: Recursion

CMSC 330: Organization of Programming Languages

Python for Non-programmers

CSE 2123 Recursion. Jeremy Morris

1 Dynamic Programming

Lab 1: Introduction to Java

Metaprogramming assignment 3

Lecture 8: Iterators and More Mutation

6.001 Notes: Section 8.1

MP 2 Continuation-Passing Style

What is Iteration? CMPT-101. Recursion. Understanding Recursion. The Function Header and Documentation. Recursively Adding Numbers

CSCI0170. Today s topics. Predicates Natural Number recursion Recursion Diagrams List recursion A first glance at the design recipe

TUPLES AND RECURSIVE LISTS 5

SCHEME The Scheme Interpreter. 2 Primitives COMPUTER SCIENCE 61A. October 29th, 2012

Transcription:

Integrated Introduction to Computer Science Hughes Lab 10: OCaml sequences, comparators, stable sorting 12:00 PM, Nov 12, 2017 Contents 1 A last OCaml type, and its utility 1 1.1 Sequences in OCaml.................................... 2 1.2 Using printing in debugging................................ 3 2 Comparators 3 3 Stable sorting 5 Objectives By the end of this lab, you will know: ˆ what comparators are ˆ how to make a stable merge-sort ˆ whether insertion sort is stable By the end of this lab, you will be able to: ˆ print out debugging information in the middle of an OCaml program ˆ sort things other than numbers, like BigNums 1 A last OCaml type, and its utility OCaml has one more type that you haven t seen, unit. The usual way to construct a unit is with empty parens: (). Open up an OCaml interpreter and try typing ();; just to see how it looks. There are other functions in OCaml that produce units. One of these is print_string. When OCaml evaluates print_string "Hello!\n", two things happen: 1. The string Hello!, followed by a newline, gets printed out. 2. The value () gets returned

Try typing print_string "Hello!\n";; to an OCaml interpreter and see what you get. Take a look at https://caml.inria.fr/pub/docs/manual-ocaml/libref/pervasives. html and read about Output functions on standard output. Now think about printing an int list. You d like to write let rec print_int_list (aloi: int list) : unit = match aloi with... This is a little tricky. At the start of the list, you want to print a left bracket. But if you call this recursively, you ll print another left bracket before the REST of the list, and so on. Here s a solution: write let rec print_int_list_contents (aloi: int list) : unit = match aloi with... which prints out the items in a list, each item (except the last) being followed by a semicolon and a space. Now how do you print a whole list? You print an open bracket, then the contents, then a right bracket. The problem is that we don t have a way to do a sequence of things in OCaml yet. (There s a very good alternative here: instead of writing a procedure that prints the list contents, you could write one that converted those contents to string form, and then the main list-printing program could put a left bracket at the front of that string, a right bracket at the end, and call print_string on the whole result. But we re walking you through this alternative to illustrate something else, so bear with us.) 1.1 Sequences in OCaml You ve seen semicolons in OCaml as a way of separating items in a list. There is another use, however: semicolons are used to form sequences. Try typing 4;5;"hello";[1;2];; into OCaml. You ll get some warnings, but the value of the expression you just typed (yes, it s an expression!) is [1;2], i.e., the last item in the sequence. What s going on here is that ; is actually an infix operator in OCaml, and the value of a ; b is just the value of b. It seems as if it d be a waste of time to ever write a sequence, because you could just have written the last item and gotten the same result. The exception is when the expression a has a side effect, like printing out some text to your terminal. Try typing print_string ("Hello!" ˆ "\n"); 4;; and see what happens. 2

There were no warnings this time. Why not? Well, the type of print_string is str ->unit, and when the semicolon operator gets anything except a unit as its first argument, you get a warning, but when it gets a unit as the first argument, it produces no warning. This is why we are doing this exercise so you are able to print out in the middle of your procedures. With this in mind, you can write let print_int_list (aloi: int list) : unit = print_string "["; print_int_list_contents aloi; print_string "]" ;; Task: Write print_int_list_contents, as well as some tests for your procedure. Why is the output type for this procedure unit? 1.2 Using printing in debugging Suppose you write a length procedure like this: let rec len(alod: 'a list) : int = match alod with [] - > 0 hd::tl - > 1 + len tl;; which happens to be perfectly OK code, but because of a mistake in some check-expect, you think it might be wrong. How can you use our print_int_list code from above to help you debug? Well, you re probably pretty confident about the base case, so let s do something with the recursive case. Because our printing procedure only works on int lists, we ll have to change the signature a little. But after that, look at this small change to the recursive case: let rec len(alod: int list) : int = match alod with [] - > 0 hd::tl - > (print_int_list tl); print_string "\n"; 1 + len tl;; Go ahead and type that in, and try computing the length of the list [1;2;3]. Helpful, eh? Task: Now write subsets in OCaml, and insert something that prints out the argument right before it does the main matching (the split between an empty list and a cons list). See what happens when you compute the subsets of [1;2;3]. You ve reached a checkpoint! Please call over a lab TA to review your work. 2 Comparators We call operators like >, <, and = comparators, because they compare values. These comparators are built in to OCaml. Moreover, they are polymorphic predicates they consume int values, or float values, etc. and they produce boolean values. Here is an example of a comparator that is not built in to OCaml. 1 It compares two strings, based on their respective lengths: 1 We wrote it ourselves! 3

let string_compare (str1 : string) (str2 : string) : bool = (String.length str1) < (String.length str2) As you can see, our string_compare predicate is designed specifically for strings. It consumes two strings, and produces true when the first is shorter than the second, and false otherwise. But here s the thing: it s hard to remember when string_compare produces true: is it when the first string is shorter than the second one, or longer than the second one? Wouldn t it be preferable if string_compare produced a more informative value, such as Less or Greater? With OCaml s powerful variant type system, we can do exactly this. First, we define a generalized comparison type: type comparison = Less Equal Greater Second, we rewrite string_compare so that it produces a value of type comparison instead of a boolean: let string_compare (str1 : string) (str2 : string) : comparison = if (String.length str1) < (String.length str2) then Less else if (String.length str1) > (String.length str2) then Greater else Equal Task: Write a procedure bignum_compare which compares two bignums. Your procedure should consume two bignum values and produce the appropriate comparison value. Hint: Remember that the number 123 is represented in reverse order by the bignum [3; 2; 1]. For example: bignum_compare [] [1 ; 2 ; 3] => Less bignum_compare [4; 7; 1] [5; 7; 1] => Less bignum_compare [4; 7; 1] [5; 7; 1; 2] => Less bignum_compare [1; 2] [2; 1] => Greater bignum_compare [1; 8; 8; 9] [1; 8; 8; 8] => Greater bignum_compare [7; 1] [7; 1] => Equal Hint: Do not use library procedures like List.length or List.reverse. They will not lead to an efficient solution. Instead, write a procedure that recurs on two lists. 4

Task: What is the run time of your bignum comparator? Task: Rewrite insertion_sort so that if it uses a comparator like bignum_compare as its last argument, so that the type becomes insertion_sort: ('a list) - > ('a - > 'a - > comparison) - > 'a list To get you started, here s the code for the ordinary insertion sort: let rec insert (n:int) (aloi: int list) : int list = match (n, aloi) with n, [] - > [n] n, (hd::tl) - > if n < hd then n::aloi else hd:: (insert n tl);; let rec insertion_sort (aloi: int list): int list = match aloi with [] - > [] hd::tl - > insert hd (insertion_sort tl);; You ll need to change all the int s to 'a, so that it can work with arbitrary data. Now define a new comparison, pair_compare, that compares two int * string pairs, and says that (n1, str1) is less than (n2, str2) exactly when n1 < n2 (i.e., it compares only the int part). Use your insertion sort to sort a list that looks like this: [ (2, "two"); (1, "first"); (1, "second"); (0, "zero"); (0, "last")] Task: Is the resulting sorted list a stable sort of the data, in the sense that if two items in the input are equal, then their order in the output is unchanged? (i.e., (1, "first") should still come before (1, "second").) Experiment to find out. You ve reached a checkpoint! Please call over a lab TA to review your work. 3 Stable sorting What about building a stable sorting algorithm? Task: Rewrite mergesort (with a comparator argument) and once again check whether it is stable, by applying it to the example above that used pair_compare. Here s a slightly modified version of the mergesort from class. The two main differences are: ˆ The code uses the compute the length of the list to split it in two approach rather than the card-dealing approach, which helps in making it a stable sort. ˆ The code tests whether the head of the left list is less than or equal to the head of the right list; this too helps in maintaining stability. 5

#use "/course/cs0170/src/ocaml/cs17setup.ml" ;; (* merge: int list - > int list - > int list input: sorted lists aloi1 and aloi2 of integers in nondecreasing order output: a list of all items of both lists, in nondecreasing order, where if elements of the two lists are equal, those coming from aloi1 come first, and in which the elements of aloi1 appear in the output in the order in which they appear in aloi1, and similarly for aloi2 *) let rec merge (aloi1: int list) (aloi2: int list): int list = match (aloi1, aloi2) with [], _ - > aloi2 _, [] - > aloi1 (hd1::tl1, hd2::tl2) - > if hd1 <= hd2 then hd1::(merge tl1 aloi2) else hd2::(merge aloi1 tl2);; check_expect (merge [1;3;4] [2; 5;6;8]) [1;2;3;4;5;6;8];; check_expect (merge [] [1;2]) [1;2];; check_expect (merge [1;2] []) [1;2];; (* take2: int - > (int list) - > (int list) * (int list) inputs: a number, n, of items to select from the input list a list, aloi, of integers output: a pair p1, p2 where p1 contains the first n items of aloi, in the order they appear in aloi, and p2 contains the remaining items, again in the order they had in aloi. *) let rec take2 (n: int) (aloi: int list): (int list) * (int list) = match (n, aloi) with 0, [] - > ([], []) 0, _ - > ([], aloi) n, [] - > failwith "No items left to take" n, hd::tl - > let (p1, p2) = take2 (n - 1) tl in (hd::p1, p2);; check_expect (take2 3 [1;2;3]) ([1;2;3], []);; check_expect (take2 0 [1;2;3]) ([], [1;2;3]);; check_expect (take2 0 []) ([], []);; check_expect (take2 3 [1;2;3;4;5]) ([1;2;3], [4;5]);; let rec split (aloi: int list): (int list) * (int list) = match aloi with [] - > ([], []) _ - > let n = List.length aloi in 6

take2 (n/2) aloi;; check_expect (split [1;2;3]) ([1], [2;3]);; check_expect (split []) ([], []);; check_expect (split [1;2;3;4]) ([1;2], [3;4]);; (* mergesort: int list - > int list input: a list, aloi, of integers output: a list containing the same integers, but sorted so that each is greater than or equal to the previous one *) let rec mergesort(aloi: int list): int list = match aloi with [] [_] - > aloi _ - > let (s1, s2) = split aloi in merge (mergesort s1) (mergesort s2);; You may need to change the #use line at the top to make it work for you. Task: Finally, make a copy of this mergesort procedure, called merge_sort_b (the b is for broken ) that uses a less-than rather than a less-than-or-equal-to comparison between hd1 and hd2, which should make the sort unstable. Then find a list of int-string pairs that are sorted unstably by this revised version. Because the code we gives you takes in int lists, you will need to convert it to take in a lists so that it could work with pairs. You ve reached a checkpoint! Please call over a lab TA to review your work. Once a lab TA signs off on your work, you ve finished the lab! Congratulations! Before you leave, make sure both partners have access to the code you ve just written. Please let us know if you find any mistakes, inconsistencies, or confusing language in this or any other CS17document by filling out the anonymous feedback form: http://cs.brown.edu/ courses/cs017/feedback. 7