Homework 6. What To Turn In. Reading. Problems. Handout 15 CSCI 334: Spring, 2017

Similar documents
Homework 11 Due Wednesday, 12/1/10

Homework 5. Notes. Turn-In Instructions. Reading. Problems. Handout 19 CSCI 334: Spring (Required) Read Mitchell, Chapters 6 and 7.

Introduction to Programming Using Java (98-388)

CS52 - Assignment 8. Due Friday 4/15 at 5:00pm.

CSE P 501 Exam 8/5/04

Homework 1. Notes. What To Turn In. Unix Accounts. Reading. Handout 3 CSCI 334: Spring, 2017

Computer Science CSC324 Wednesday February 13, Homework Assignment #3 Due: Thursday February 28, 2013, by 10 p.m.

Java Design Goals. Lecture 32: Java. Java Original implementations slow! Exceptions & Subtyping. - void method readfiles() throws IOException {...}!

Problem Set CVO 103, Spring 2018

CS2112 Fall Assignment 4 Parsing and Fault Injection. Due: March 18, 2014 Overview draft due: March 14, 2014

CSE 413 Winter 2001 Midterm Exam

CS2110 Assignment 2 Lists, Induction, Recursion and Parsing, Summer

Homework 8. What To Turn In. Reading. Self Check. Problems. Handout 19 CSCI 334: Spring, 2017

CSE 341, Spring 2011, Final Examination 9 June Please do not turn the page until everyone is ready.

COMPUTER SCIENCE TRIPOS

CSci 4223 Lecture 18 April 3, 2013 Topics: OOP vs. FP

CSCI 3155: Homework Assignment 3

These notes are intended exclusively for the personal usage of the students of CS352 at Cal Poly Pomona. Any other usage is prohibited without

to calculate Fib(N) very quickly 1 Task 1: High-school algebra helps to design your program

syntax tree - * * * * * *

ASTS, GRAMMARS, PARSING, TREE TRAVERSALS. Lecture 14 CS2110 Fall 2018

Homework 4 Due Friday, 10/3/08

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

There are some situations in which recursion can be massively inefficient. For example, the standard Fibonacci recursion Fib(n) = Fib(n-1) + Fib(n-2)

syntax tree - * * * - * * * * * 2 1 * * 2 * (2 * 1) - (1 + 0)

CS558 Programming Languages

Basic Operations jgrasp debugger Writing Programs & Checkstyle

APCS Semester #1 Final Exam Practice Problems

CIS 110 Introduction To Computer Programming. February 29, 2012 Midterm

Answers to review questions from Chapter 2

Prof. Mohamed Hamada Software Engineering Lab. The University of Aizu Japan

15 150: Principles of Functional Programming. Exceptions

Homework 4. Notes. Turn-In Instructions. Reading. Self Check. Handout 16 CSCI 334: Spring 2018

Functions and Objects. Week 7: Symbolic Computation

SCHEME AND CALCULATOR 5b

Assignment 6. Computer Science 52. Due Friday, November 9, 2018, at 5:00 pm

CSCC24 Functional Programming Typing, Scope, Exceptions ML

COMPUTER SCIENCE TRIPOS

CISC 3115 Modern Programming Techniques Spring 2018 Section TY3 Exam 2 Solutions

Question Points Score

Project Compiler. CS031 TA Help Session November 28, 2011

Object Oriented Programming

CS 3410 Ch 7 Recursion

ECE 2400 Computer Systems Programming Fall 2018 Topic 2: C Recursion

Midterm I - CSE11 Fall 2013 CLOSED BOOK, CLOSED NOTES 50 minutes, 100 points Total.

Program Representations

CS 330 Homework Comma-Separated Expression

CSCI-1200 Data Structures Fall 2018 Lecture 22 Hash Tables, part 2 & Priority Queues, part 1

Semantic Analysis. Compiler Architecture

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

UNIVERSITETET I OSLO

Grammars and Parsing, second week

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

In this chapter you ll learn:

Compiler Theory. (Semantic Analysis and Run-Time Environments)

19 Much that I bound, I could not free; Much that I freed returned to me. Lee Wilson Dodd

Introduction to Functional Programming: Lecture 7 2 Functions as innite data structures Ordinary ML data structures are always nite. We can, however,

More Complicated Recursion CMPSC 122

Binary Search. Roland Backhouse February 5th, 2001

CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion. Zach Tatlock Winter 2018

1 Epic Test Review 2 Epic Test Review 3 Epic Test Review 4. Epic Test Review 5 Epic Test Review 6 Epic Test Review 7 Epic Test Review 8

CSE341, Spring 2013, Final Examination June 13, 2013

CS 360 Programming Languages Interpreters

Expressions and Casting

Topic 7: Algebraic Data Types

Dynamic Programming. See p of the text

At build time, not application time. Types serve as statically checkable invariants.

Homework 1. Reading. Problems. Handout 3 CSCI 334: Spring, 2012

CSCI 3155: Homework Assignment 4

CSCI-GA Final Exam

CIS 194: Homework 3. Due Wednesday, February 11, Interpreters. Meet SImPL

SML Style Guide. Last Revised: 31st August 2011

Haskell s Take on the Expression Problem

Postfix Notation is a notation in which the operator follows its operands in the expression (e.g ).

COMP-421 Compiler Design. Presented by Dr Ioanna Dionysiou

CS558 Programming Languages

CS 61B Discussion Quiz 1. Questions

CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square)

CSE 12 Abstract Syntax Trees

Introduction to MiniSim A Simple von Neumann Machine

Topics. Java arrays. Definition. Data Structures and Information Systems Part 1: Data Structures. Lecture 3: Arrays (1)

Homework 7. What To Turn In. Reading. Self Check. Handout 18 CSCI 334: Spring, 2017

A Brief Introduction to Standard ML

CA Compiler Construction

CSCI Compiler Design

Advanced Java Concepts Unit 3: Stacks and Queues

Lecture 10: Recursion vs Iteration

Announcements. Lab Friday, 1-2:30 and 3-4:30 in Boot your laptop and start Forte, if you brought your laptop

DO NOT OPEN UNTIL INSTRUCTED

Design Patterns: State, Bridge, Visitor

CMPSCI 250: Introduction to Computation. Lecture #14: Induction and Recursion (Still More Induction) David Mix Barrington 14 March 2013

Lecture 8: Recursion and Iteration. Exceptions. Declarative Programming.

Assignment 7. Computer Science 52. Due November 30, 2018, at 5:00 pm

Category Item Abstract Concrete

Assignment 5. Introduction

SOFTWARE DEVELOPMENT 1. Recursion 2018W A. Ferscha (Institute of Pervasive Computing, JKU Linz)

A lexical analyzer generator for Standard ML. Version 1.6.0, October 1994

A LISP Interpreter in ML

CS52 - Assignment 7. Due Friday 11/13 at 5:00pm.

CSCI-1200 Data Structures Spring 2018 Lecture 7 Order Notation & Basic Recursion

Transcription:

Homework 6 Due 11 April Handout 15 CSCI 334: Spring, 2017 What To Turn In Please hand in work in two pieces, one for the Problems and one for the Programming (Partner Optional): Problems: Turn in handwritten or typed answers by the due date. Be sure your work is stapled and that your answers are clearly marked and in the correct order. Programming: Turn in a printout of your code separately from your problem answers. If you worked with a partner, only one person needs to hand in a printout, but be sure both names are at the top of the file. Turn in an electronic copy as well using the instructions at the end of the programming questions. Reading 1. (Required) Read Mitchell, Chapter 8.1 8.2. 2. (Required) Mitchell, Chapter 10. Problems Q1. (10 points)....................................................................... Exceptions Consider the following functions, written in ML: exception Excpt of int; fun twice(f,x) = f(f(x)) handle Excpt(x) => x; fun pred(x) = if x = 0 then raise Excpt(x) else x-1; fun dumb(x) = raise Excpt(x); fun smart(x) = (1 + pred(x)) handle Excpt(x) => 1; What is the result of evaluating each of the following expressions? (a) twice(pred,1); (b) twice(dumb,1); (c) twice(smart,0); In each case, be sure to describe which exception gets raised and where. Q2. (15 points)............................... Equivalence of Abstract Data Types Mitchell, Problem 9.2 1

Q3. (15 points).......................................................... Expression Objects We now look at an object-oriented way of representing arithmetic expressions given by the grammar e ::= num e + e We begin with an abstract class called SimpleExpr. While this class has no instances, it lists the operations common to all instances of this class or subclasses. In this case, it is just a single method to return the value of the expression. abstract class SimpleExpr { abstract int eval(); Since the grammar gives two cases, we have two subclasses of SimpleExpr, one for numbers and one for sums. class Number extends SimpleExpr { int n; public Number(int n) { this.n = n; int eval() { return n; class Sum extends SimpleExpr { SimplExpr left, right; public Sum(SimpleExpr left, SimpleExpr right) { this.left = left; this.right = right; int eval() { return left.eval() + right.eval(); (a) Product Class Extend this class hierarchy by writing a Times class to represent product expressions of the form e ::=... e e (b) Method Calls Suppose we construct a compound expression by SimpleExpr a = new Number(3); SimpleExpr b = new Number(5); SimpleExpr c = new Number(7); SimpleExpr d = new Sum(a,b); SimpleExpr e = new Times(d,c); and send the message eval to e. Explain the sequence of calls that are used to compute the value of this expression: e.eval(). What value is returned? (c) Comparison to Type Case constructs Let s compare this programming technique to the expression representation used in ML, in which we declared a datatype and defined functions on that datatype by pattern matching. The following eval function is one form of a type case operation, in which the program inspects the actual tag (or type) of a value being manipulated and executes different code for the different cases: 2

datatype MLExpr = Number of int Sum of MLExpr * MLExpr; fun eval (Number(x)) = x eval (Sum(e1,e2)) = eval(e1) + eval(e2); This idiom also comes up in class hierarchies or collections of structures where the programmer has included a Tag field in each definition that encodes the actual type of an object. i. Discuss, from the point of view of someone maintaining and modifying code, the differences between adding the Times class to the object-oriented version and adding a Times constructor to the MLExpr datatype. In particular, what do you need to add/change in each of the programs. Generalize your observation to programs containing several operations over the arithmetic expressions, and not just eval. ii. Discuss the differences between adding a new operation, such as tostring, to each way of representing expressions. Assume you have already added the product representation so that there is more than one class with a nontrivial eval method. Programming [Partner Optional] P1. (10 points).............................................................. Exceptions in ML The function stringtonum defined below uses two auxiliary functions to convert a string of digits into a non-negative integer. (* Convert one character to a numeric digit. *) fun chartonum c = ord c - ord #"0"; fun calclist (nil,n) = n calclist (fst::rest,n) = calclist(rest,10 * n + chartonum fst); (* Convert a string of digits to a number. The explode function converts a string to a list of characters. *) fun stringtonum s = calclist(explode s, 0); For instance, stringtonum "3405" returns the integer 3405. (The function explode converts a string into a list of characters, and ord returns the ASCII integer value for a character.) Unfortunately, calclist returns a spurious result if the string contains any non-digits. For instance, stringtonum "3a05" returns 7905, while stringtonum " 405" returns 15595. This occurs because chartonum will convert any character, not just digits. We can attempt to fix this by having chartonum raise an exception if it is applied to a non-digit. (a) Revise the definition of chartonum to raise an exception, and then modify the function stringtonum so that it handles the exception, returning 1 if there is a non-digit in the string. You should make no changes to calclist. (b) Implement ML functions to provide the same behavior (including returning 1 if the string includes a non-digit) as in the first part, but without using exceptions. While you may change any function, try to preserve as much of the structure of the original program as possible. (c) Which implementation do you prefer? Why? Answer this as a comment in the code. 3

P2. (15 points)................................................................... Tail Recursion (a) The dot product of two vectors [a 1,..., a n ] and [b 1,..., b n ] is the sum a 1 b 1 + a 2 b 2 + + a n b n. For example, [1, 2, 3] [ 1, 5, 3] = 1 1 + 2 5 + 3 3 = 18 Implement the function dotprod: int list -> int list -> int to compute the dot product of two vectors represented as lists. You should write this using tail-recursion, so your dotprod function will probably just be a wrapper function that calls a second function that does all the work. If passed lists of different length, your function should raise a DotProd exception. You will need to declare this type of exception, but you need not catch it. - dotprod [1,2,3] [~1,5,3]; val it = 18 : int - dotprod [~1,3,9] [0,0,11]; val it = 99 : int - dotprod [] []; val it = 0 : int - dotprod [1,2,3] [4,5]; uncaught exception DotProd (b) The numbers in the Fibonacci sequence are defined as: F (0) = 0 F (1) = 1 F (n) = F (n 1) + F (n 2) Thus, the sequence is 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, etc. The following defines a function that returns the n-th Fibonacci number. fun slow_fib(0) = 0 slow_fib(1) = 1 slow_fib(n) = slow_fib(n-1) + slow_fib(n-2); Unfortunately, computing slow fib(n) requires O(2 n ) time. Define a tail recursive function fast fib that can compute F (n) in O(n) time by using tail recursion. (As above, fast fib will most likely be a wrapper that calls a tail-recursive function.) The tail-recursive function should have only one recursive call in its definition. - fast_fib 0 val it = 0 : int - fast_fib 1 val it = 1 : int - fast_fib 5 val it = 5 : int - fast_fib 10 val it = 55 : int (Hint: When converting sumsquares to tail-recursive form, we introduced one auxiliary parameter to accumulate the result of the single recursive call in that function. How many auxiliary parameters do you think we will need for fibtail?) Please use turnin to submit the code for this problem, and also include a printout with your problem set. 4

P3. (20 points)....................................................... Visitor Design Pattern The code for this question is located on the handouts webpage in the ExprVisitor.java file. Download that code and compile it with javac. Include answers to the questions below as comments at the top of that file. The extension and maintenance of an object hierarchy can be greatly simplified (or greatly complicated) by design decisions made early in the life of the hierarchy. This question explores various design possibilities for an object hierarchy (like the one above) that represents arithmetic expressions. The designers of the hierarchy have already decided to structure it as shown below, with a base class Expr and derived classes Number, Sum, Times, and so on. They are now contemplating how to implement various operations on Expressions, such as printing the expression in parenthesized form or evaluating the expression. They are asking you, a freshly-minted language expert, to help. The obvious way of implementing such operations is by adding a method to each class for each operation. This version is not in the starter code, but the expression hierarchy would look like the following in this scenario: abstract class Expr { public abstract String tostring(); public abstract int eval(); class Number extends Expr { int n; public Number(int n) { this.n = n; public String tostring() {... public int eval() {... class Sum extends Expr { Expr left, right; public Sum(Expr left, Expr right) { this.left = left; this.right = right; public String tostring() {... public int eval() {... Suppose there are n subclasses of Expr altogether, each similar to Number and Sum shown here. How many classes would have to be added or changed to add each of the following things? (a) A new class to represent division expressions. (b) A new operation to graphically draw the expression parse tree. Another way of implementing expression classes and operations uses a pattern called the Visitor Design Pattern. In this pattern, each operation is represented by a Visitor class. Each Visitor class has a visitclass method for each expression class Class in the hierarchy. Each expression class Class is set up to call the visitclass method to perform the operation for that particular class. In particular, each class in the expression hierarchy has an accept method which accepts a Visitor as an argument and allows the Visitor to visit the class and perform its operation. The expression class does not need to know what operation the visitor is performing. If you write a Visitor class ToString to construct a string representation of an expression tree, it would be used as follows: 5

Expr exptree =...some code that builds the expression tree...; ToString printer = new ToString(); String stringrep = exptree.accept(printer); System.out.println(stringRep); The first line defines an expression, the second defines an instance of your ToString class, and the third passes your visitor object to the accept method of the expression object. The expression class hierarchy using the Visitor Design Pattern has the following form, with an accept method in each class and possibly other methods. Since different kinds of visitors return different types of values, the accept method is parameterized by the type that the visitor computes for each expression tree: abstract class Expr { abstract <T> T accept(visitor<t> v); class Number extends Expr { int n; public Number(int n) { this.n = n; public <T> T accept(visitor<t> v) { return v.visitnumber(this.n); class Sum extends Expr { Expr left, right; public Sum(Expr left, Expr right) { this.left = left; this.right = right; public <T> T accept(visitor<t> v) { T leftval = left.accept(v); T rightval = right.accept(v); return v.visitsum(leftval, rightval); The associated Visitor abstract class, naming the methods that must be included in each visitor, and the ToString visitor, have this form: abstract class Visitor<T> { abstract T visitnumber(int n); abstract T visitsum(t left, T right); class ToString extends Visitor<String> { public String visitnumber(int n) { return "" + n; public String visitsum(string left, String right) { return "(" + left + " + " + right + ")"; Here is an example of using the visitor to evaluate and print an expression. 6

class ExprVisitor { public static void main(string s[]) { Expr e = new Sum(new Number(3), new Number(2)); ToString printer = new ToString(); String stringrep = e.accept(printer); System.out.print(stringRep); (c) Starting with the call to e.accept(printer), what is the sequence of method calls that will occur while building the string for the expression tree e? (d) Add the following classes to the source file. You will need to change some of the existing classes to accomodate them. i. An Eval visitor class that computes the value of an expression tree. The visit methods should return an Integer. Recall that Java 1.5 has auto-boxing, so it can convert int values to Integer objects and vice-versa, as needed. ii. Subtract and Times classes to represent subtraction and product expressions. iii. A Compile visitor class that returns a sequence of stack-based instructions to evaluate the expression. You may use the following stack instructions (Refer back to HW 3 if you need a refresher on how these instructions operate): PUSH(n) ADD MULT SUB DIV SWAP The visit methods can simply return a String containing the sequence of instructions. For example, compiling 3 (1 2) should return the string PUSH(3) PUSH(1) PUSH(2) SUB MULT The instruction sequence should just leave the result of computing the expression on the top of the stack. Hint: the order of instructions you need to generate is exactly a post-order traversal of the expression tree. Aside: Most modern compilers (including the Sun Java compiler) are implemented using the Visitor Pattern. The compilation process is really just a sequence of visit operations over the abstract syntax tree. Common steps include visitors 1) to resolve the declaration to which each variable access refers; 2) to perform type checking; 3) to optimize the program; 4) to generate code as above; and so on. Suppose there are n subclasses of Expr, and m subclasses of Visitor. How many classes would have to be added or changed to add each of the following things using the Visitor Design Pattern? (e) A new class to represent division expressions. (f) A new operation to graphically draw the expression parse tree. The designers want your advice. (g) Under what circumstances would you recommend using the standard design? (h) Under what circumstances would you recommend using the Visitor Design Pattern? What To Turn In for the Programming. Be sure your code is documented and include your name at the top of the file. Include a printout of your files for each question separately from the write-up you hand in. 7

Submit an electronic copy of those files with the command turnin -c 334 file, where file is the name of your source file. You may submit the file more than once if you find a mistake or wish to change what you submitted the first time. If you worked with a partner, please be sure the code includes both names. Only one person needs to submit a paper copy and run turnin. P4. (15 points)................................................. Five 5 s (Bonus Question) Consider the well-formed arithmetic expressions using the numeral 5. These are expressions formed by taking the integer literal 5, the four arithmetic operators +, -, *, and /, and properly placed parentheses, such as 5, 5+5, (5 + 5) * (5-5 / 5), and so on. (Such expressions correspond to binary trees in which the internal nodes are operators and every leaf is a 5.) Write a ML program to answer one or more of the following questions: (a) What is the smallest positive integer than cannot be computed by an expression involving exactly five 5 s? (b) What is the largest prime number that can computed by an expression involving exactly five 5 s? (c) Exhibit an expression that evaluates to that prime number. You should start by defining a datatype to represent arithmetic expressions involving 5 and the arithmetic operations, as well as an eval function to evaluate them. This question involves only integer arithmetic, so be sure to use div for division. You should then write code to generate all expressions containing a fixed number of 5 s. Answering the questions will then involve an exhaustive search (for all numbers that can be computed with a fixed number of 5 s), so good programming techniques are important. Avoid any unnecessarily time-consuming or memory-consuming operations. You may also have to do something special to avoid division by zero inside eval, perhaps with exception handlers. (For those who have taken or are taking 256: while there are many possible ways to solve this problem, it is one very well-suited for dynamic programming...) Submit your code with turnin, and please include a printout with your problem set. 8