Programming Principles

Similar documents
Programming Principles

Programming Principles

Functional Programming

Programming Principles

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

Exercise 1: Graph coloring (10 points)

UNIVERSITY OF TORONTO Faculty of Arts and Science. Midterm Sample Solutions CSC324H1 Duration: 50 minutes Instructor(s): David Liu.

CSCI-GA Final Exam

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

Programming Paradigms Written Exam (6 CPs)

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

Administrivia. Last modified: Fri Aug 25 10:59: CS61B: Lecture #2 1

CS205: Scalable Software Systems

Project 1. due date Sunday July 8, 2018, 12:00 noon

Programming Paradigms Written Exam


Parallel Programming

Problem Solving for Intro to Computer Science

Download the forcomp.zip handout archive file and extract it somewhere on your machine.

You ve encountered other ways of signalling errors. For example, if you lookup an unbound key in a hashtable, Java (and Scala) produce nulls:

Structure and Interpretation of Computer Programs

AP Computer Science Summer Work Mrs. Kaelin

CS 61A Interpreters, Tail Calls, Macros, Streams, Iterators. Spring 2019 Guerrilla Section 5: April 20, Interpreters.

Programming Languages 3. Definition and Proof by Induction

CPL 2016, week 10. Clojure functional core. Oleg Batrashev. April 11, Institute of Computer Science, Tartu, Estonia

CSC 1351: Quiz 6: Sort and Search

CS1 Lecture 5 Jan. 26, 2018

Exercise 6 Multiple Inheritance, Multiple Dispatch and Linearization November 4, 2016

Problem Set 4: Streams and Lazy Evaluation

COMPUTER SCIENCE TRIPOS

Introduction to Sets and Logic (MATH 1190)

CSE Programming Languages Midterm - Winter 2010

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

COS 320. Compiling Techniques

List Functions, and Higher-Order Functions

In addition to the correct answer, you MUST show all your work in order to receive full credit.

Excerpt from "Art of Problem Solving Volume 1: the Basics" 2014 AoPS Inc.

List are immutable Lists have recursive structure Lists are homogeneous

Structure and Interpretation of Computer Programs

Object Oriented Programming with Java

MICROPROCESSOR SYSTEMS INTRODUCTION TO PYTHON

1007 Imperative Programming Part II

CPSC 121 Some Sample Questions for the Final Exam Tuesday, April 15, 2014, 8:30AM

Lesson 10A OOP Fundamentals. By John B. Owen All rights reserved 2011, revised 2014

Lesson 1A - First Java Program HELLO WORLD With DEBUGGING examples. By John B. Owen All rights reserved 2011, revised 2015

CSCI 3155: Lab Assignment 6

CSc 520. Principles of Programming Languages 11: Haskell Basics

Lab Manual. Program Design and File Structures (P): IT-219

CSE 341 Section 5. Winter 2018

CS 320: Concepts of Programming Languages

CS205: Scalable Software Systems

CSc 372. Comparative Programming Languages. 4 : Haskell Basics. Department of Computer Science University of Arizona

CSC 207 (16fa) Practice Exam 2 Page 1 of 13. Practice Exam 2 (Exam 2 date: Friday 11/18) Logistics:

Programming Paradigms Written Exam (6 CPs)

Public-Service Announcements

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

11 Parameterized Classes

Curriculum Map Grade(s): Subject: AP Computer Science

Programming. We will be introducing various new elements of Python and using them to solve increasingly interesting and complex problems.

Example 2: Simplify each of the following. Round your answer to the nearest hundredth. a

CS150 Sample Final Solution

Announcements. 1. Forms to return today after class:

EXAM Computer Science 1 Part 1

Final Examination: Topics and Sample Problems

Chapter 1 An Introduction to Computer Science. INVITATION TO Computer Science 1

cs1120: Exam 2 Due: Thursday Nov 29 at 3:30pm (in class)

Topic 5: Higher Order Functions

Topic 5: Higher Order Functions

CS150 Sample Final. Name: Section: A / B

In Fig. 3.5 and Fig. 3.7, we include some completely blank lines in the pseudocode for readability. programs into their various phases.

Exam 1 Format, Concepts, What you should be able to do, and Sample Problems

Outline. policies. with some potential answers... MCS 260 Lecture 19 Introduction to Computer Science Jan Verschelde, 24 February 2016

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

Midterm Exam 2B Answer key

UNIVERSITY OF CALIFORNIA Department of Electrical Engineering and Computer Sciences Computer Science Division. P. N. Hilfinger.

Lesson 3-4: Using Collectors

Programming Paradigms Languages F28PL, Lecture 1

Chapter 2: Data and Expressions

Programming Languages and Techniques (CIS120)

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

CS1 Lecture 5 Jan. 25, 2019

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

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

There are three questions on this exam. You have 2 hours to complete it. Please indent your program so that it is easy for the grader to read.

11. a b c d e. 12. a b c d e. 13. a b c d e. 14. a b c d e. 15. a b c d e

Exercise 6 Multiple Inheritance, Multiple Dispatch and Linearization November 3, 2017

QUIZ 2 Introduction to Computer Science (COMP 250) Mon. March 2, 2009 Professor Michael Langer

A Concepts-Focused Introduction to Functional Programming Using Standard ML Sample Exam #1 Draft of August 12, 2010

More on Arrays CS 16: Solving Problems with Computers I Lecture #13

CIS 110 Introduction to Computer Programming 8 October 2013 Midterm

Collections. Lists, Tuples, Sets, Dictionaries

Streams. CS21b: Structure and Interpretation of Computer Programs Spring Term, 2004

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

Computer Programming C++ (wg) CCOs

University of Washington CSE 140 Data Programming Winter Final exam. March 11, 2013

COMP 202 Recursion. CONTENTS: Recursion. COMP Recursion 1

CSSE 120 Introduction to Software Development Practice for Test 1 paper-and-pencil part Page 1 of 6

3. Convert 2E from hexadecimal to decimal. 4. Convert from binary to hexadecimal

Computer System Architecture Quiz #1 March 8th, 2019

CS115 - Module 9 - filter, map, and friends

Transcription:

Programming Principles Midterm Exam Friday, November 9th 2012 First Name: Last Name: Your points are precious, don t let them go to waste! Your Name Work that can t be attributed to you is lost: write your name on each sheet of the exam. Your Time All points are not equal. Note that we do not think that all exercises have the same difficulty, even if they have the same number of points. Your Attention The exam problems are precisely and carefully formulated, some details can be subtle. Pay attention, because if you do not understand a problem, you can not obtain full points. Exercise Points Points Achieved 1 10 2 10 3 10 Total 30

Exercise 1: Grades (10 points) In this exercise we analyze the quiz grades of students on a course. Each student is represented by his/her name - a unique String. Grades are represented as Ints from 1 to 6. On each quiz the student receives a certain grade - this is the student s Result on a particular quiz: type Result = (String, Int) where the first element of the pair is the student s name, and the second is their grade. A quiz is defined as a list of results for each student: type Quiz = List[Result] A quiz will always have grades for all the students enrolled in the course. Finally, a course is simply a list of quizzes: type Course = List[Quiz] Here is an example of the course called Programming Principles, which consists of five students and three quizzes: val programmingprinciples = List( List( ("Johnny Depp", 1), ("Matt Damon", 3), ("Scott Bakula", 6), ("Lukas Rytz", 6), ("Mickey Mouse", 1) ), List( ("Johnny Depp", 3), ("Matt Damon", 2), ("Scott Bakula", 6), ("Lukas Rytz", 5), ("Mickey Mouse", 1) ), List( ("Johnny Depp", 4), ("Matt Damon", 4), ("Scott Bakula", 6), ("Lukas Rytz", 6), ("Mickey Mouse", 1) ) ) We suggest that you consider using the following collection methods for solving this exercise: 2

def map[u](f: T = U): List[U] a new collection which contains the elements of this collection, transformed by the function f def map[p, Q] (f: (K, V) => (P, Q)): Map[P, Q] def filter(p: T => Boolean): List[T] def filter(p: (K, V) => Boolean): Map[K, V] def take(n: Int): List[T] def takewhile(p: T => Boolean): List[T] def sortby[u](f: T => U): List[T] def groupby[k](f: T => K): Map[K, List[T]] def flatten: List[T] def tomap: Map[K, V] def tolist: List[T] def foldleft[u](z: U) (f: (U, T) => U): U def foldleft[u](z: U) (f: (U, (K, V)) => U): U def length: List[T] def size: List[T] a new map which contains the key-value pairs of this map, transformed by the function f a new collection which contains only those elements of this collection which satisfy the predicate p a new map which contains only those key-value pairs of this map which satisfy the predicate p a new collection which contains only the first n elements of this collection (or all if size is less than n) a new collection which contains the longest prefix of the elements of this collection which satisfy the predicate p a new sequence which contains the elements of this sequence in a sorted order determined by the function f useful when elements of the collection are not ordered (e.g. Tuple2), but they can be mapped into some other element type which is ordered (e.g. Double) a map which contains all the elements of this collection grouped by the mapping function f the elements which mapped into the same key are put into the same group given that this collection has collections as its elements, this returns a flattened collections (e.g. List(List(1, 2), List(3)) becomes List(1, 2, 3)) given that this collection contains pairs of type (K, V), this returns a map with keys of type K and values of type V converts this collection into a list if this collection is a Map[K, V], then the resulting list will contain pairs (K, V) folds the elements of this collection by applying f to all the elements folds the key-value pairs of this map by applying f to all the elements returns the length of this sequence returns the size of this collection (same as length, but works for any collection type, not just sequences) The methods listed above work for all collection types, not just lists for example, you can replace the return type List with a return type Map in the type signatures above. However, methods sortby and length can only be called on sequences, like List. You are allowed use other methods as well, but the solution should be the most elegant if you use the suggested methods. Each part of the exercise is independent of the other parts you do not have to solve part 1 to solve part 2. But in any part you can reuse the methods defined in the earlier parts. Part 1: Quiz Grade Means Write the method quizmeans which, given a course, computes the list of mean grades of all the quizzes in that course: 3

def quizmeans(course: Course): List[Float] =??? A mean grade of a quiz is defined as the sum of the grades of all the students divided by the number of students. Part 2: Student Grade Means Write the method studentmeans which, given a course, computes the mean grades of all the students in that course: def studentmeans(course: Course): Map[String, Float] =??? The method should return a Map mapping each student to his mean grade. The mean grade of a student is defined as the sum of his grades on all the quizzes divided by the number of quizzes. Part 3: Top Students Write the method topstudents which, given a course and the number of top students n, computes the n top students on the course. def topstudents(course: Course, n: Int): List[String] =??? The top n students are those n students with the highest mean grades. You can assume that no two students have the same mean grade. Hint: in any part of the exercise you can use one of the methods defined earlier. Part 4: Passing Students Write the method passingstudents which, given a course, computes the list of the students which passed the course: def passingstudents(course: Course): List[String] =??? The students that passed the course are those whose mean grade is greater than or equal to 3.5. Part 5: Grade histogram In the final part of this exercise, you will compute the number of students per each final grade. A final grade is obtained by computing the mean grade of the student and then rounding it to the nearest integer. The assignment from a grade to the number of students with that grade is called a grade histogram, and we model it with a Histogram datatype: type Histogram = Map[Int, Int] For example, if there were 3 students John Rambo, Judge Dredd and Rocky Balboa, and they have the mean grades 3.3, 3.2 and 6.0, respectively, then the histogram is: Map(3 -> 2, 6 -> 1) 4

because there were 2 students with a mean grade which rounds to 3, and a single student with a result of 6. Note that if zero students have a certain grade, then you do not have to include it in the histogram. Above, none of the students have a grade 5, so the key 5 is not in the Map. Write the method histogram which, given a course, computes the grade histogram of the course: def histogram(course: Course): Histogram =??? Hint: consider using the math.round(x: real number to an integer number. Float) method from the Scala standard library which rounds a 5

Exercise 2: Hamming Numbers (10 points) In this exercise we will work with Hamming numbers. On Wikipedia there are two definitions: Hamming numbers are numbers that entirely divide a power of 60 Hamming numbers have the form 2 i 3 j 5 k, where i, j and k are 0 As an example, we verify that 48 is a Hamming number. We list the powers of 60 (on the left) and see that 48 divides 60 2 without remainder (on the right): 60 0 = 1 1 mod 48 = 1 60 1 = 60 60 mod 48 = 12 60 2 = 3600 3600 mod 48 = 0 We can easily verify that 48 also matches the second definition of Hamming numbers: 48 = 2 4 3 = 2 4 3 1 5 0, so we have i = 4, j = 1 and k = 0. The goal of this exercise is to verify that the two definitions are indeed equivalent. We will implement the two definitions and compare the results. Since we are dealing with large numbers we use BigInt instead of Int in this exercise. You can work with BigInts just like with ordinary integers. The following methods of the class Stream[T] might be useful for solving this exercise. def #::[T](x: T): Stream[T] def head: T def tail: Stream[T] def zip[u](that: Stream[U]): Stream[(T,U)] def take(n: Int): Stream[T] def forall(p: T => Boolean): Boolean def exists(p: T => Boolean): Boolean def map[u](f: T => U): Stream[U] def filter(p: T => Boolean): Stream[T] prepends the element x to this stream the first element of this stream this stream without its first element a stream whose elements are pairs of the elements of the streams this and that a finite stream consisting of the first n elements of this stream true if p holds for every element in this stream true if p holds for some element in this stream a stream which contains the elements of this stream, transformed by the function f the stream of elements from this stream that satisfy predicate p First definition To implement the first definition, we begin with an infinte stream consisting of all powers of 60: val powersofsixty: Stream[BigInt] =??? powersofsixty.take(4).tolist // should give List(1, 60, 3600, 216000) We also need the infinite stream that counts from 1 upwards: val fromone: Stream[BigInt] =??? fromone.take(3).tolist // should give List(1, 2, 3) 6

The Hamming numbers can now be obtained by filtering the stream fromone and keeping only numbers which divide a power of sixty. We write a predicate function dividespowerofsixty(i: BigInt): Boolean that returns true if i is a divisor of 60 n for some n 0. However, we can obviously not look at all the powers of 60, there are infinitely many. Instead we use a conservative approximation: to find out if i divides any power of 60, the largest power of 60 we have to check is p = 60 log 2 (i). If i doesn t divide p, then it also does not divide any larger power of 60. def log2(d: Double): Double = math.log(d) / math.log(2) def maxexponent(i: BigInt): Int = math.ceil(log2(i.doublevalue)).toint def dividespowerofsixty(i: BigInt): Boolean =??? Now you can define the first stream of hamming numbers: val hamming1: Stream[BigInt] =??? Second definition The second definition of Hamming numbers will lead to a more efficient solution than the first one: instead of checking a property for each number the numbers are computed directly. An algorithmic description to compute Hamming numbers is the following: The number 1 is a Hamming number If x is a Hamming number, the numbers 2 x, 3 x and 5 x are also Hamming numbers If we implement this using a recursive value, we need a way to merge two streams into one. This job is done by mergeascending: it merges two monotonically growing streams into one by taking the smaller of the two head elements and merging the remaining elements recursively. If both input streams have the same head element, then one of the two should be dropped (in other words, the resulting stream should not have duplicates). You can assume that both input streams are infinite. def mergeascending(s1: Stream[BigInt], s2: Stream[BigInt]): Stream[BigInt] =??? mergeascending(1 #:: 4 #::..., 2 #:: 4 #:: 5 #::...) // should give 1 #:: 2 #:: 4 #:: 5 #::... Note that you can merge three streams into one by using mergeascending twice: mergeascending(s1, mergeascending(s2, s3)) Now we are ready to implement the stream of Hamming numbers: val hamming2: Stream[BigInt] =??? Comparing the two streams To see if the two streams hamming1 and hamming2 contain the same elements, write an expression that evaluates to true if the first 100 elements of the two streams are the same, and false otherwise: val ok: Boolean =??? 7

Exercise 3: Abstract Syntax Trees (10 points) The toy programming language Funny supports decimal numbers, e.g. 1 or 42, and function applications, e.g. plus(2, -2) or div(1, plus(2, -2)). The language is as simple as that. Funny doesn t support conditional expressions, operators or even function definitions - it s just numbers and calls to functions. When designing a compiler for a programming language it is common to represent programs as abstract syntax trees, recursive data structures which express code hierarchically. In funnyc, the Funny compiler, abstract syntax trees are encoded using two case classes: Number and Apply, which both inherit from a common superclass Tree. abstract class Tree case class Number(n: Int) extends Tree case class Apply(fun: String, args: List[Tree]) extends Tree These case classes can represent the aforementioned Funny programs as follows: Program Abstract syntax tree 1 Number(1) 42 Number(42) plus(2, -2) div(1, plus(2, -2)) Apply("plus", List(Number(2), Number(-2))) Apply("div", List(Number(1), Apply("plus", List(Number(2), Number(-2))))) Part 1 Convert the following two Funny programs into their abstract syntax tree representation: a) plus(1, plus(2, 3)), b) plus(plus(1, 2), 3). Are the resulting trees the same? Part 2 Back then, when Funny only supported numbers, the compiler was easy to grasp. However with the recent addition of function calls, developers of funnyc started experiencing problems with debugging. Help the developers by writing a prettyprinting function for Funny abstract syntax trees with the signature: def prettyprint(tree: Tree): String. The prettyprinter should convert syntax trees into equivalent Funny source code, like shown in the left column of the example table above. Note. Use the tostring method to convert numbers to strings. For example, 42.toString produces "42". Part 3 Despite being perceived by some as overly complex, Funny has quickly gained traction on Twitter. New feature requests are abundant. One of those is preventing division by zero errors, which happen when the function named div is called with two arguments, the second of which is 0. Write a function def divsbyzero(tree: Tree): List[Tree], which given an abstract syntax tree of a Funny program, returns all divisions by zero which occur in that program. Note. You only need to detect the most blatant division by zero mistakes, i.e. just the function applications having the form of div(..., 0). You don t have to account for expressions like div(1, plus(-2, 2)). 8