tutorial6

advertisement
+
Tutorial 6
Midterm Review
+
Reminder

Midterm is this Monday at 7pm – 8:50pm

Look up your seat on the course webpage
+
Design Recipe

Contracts:

Use the form fun_name: types consumed -> type produced


Use the single arrow in contracts!
Make sure you use the correct type names (i.e Str not String, Num
not Number, etc.)

Do not pluralize your type names

Capitalize your type names

Don’t write “Structure” as a type, use the actual structure name

Use variables to show the relation between types consumed and
produced


i.e. (X -> Y) -> Y instead of (Any -> Any) -> Any
Requirements:

Include requirements to any of the types consumed, if it has any
+


Purpose:

Make sure you mention all of the parameter names in your
purpose and how they relate to what is being produced

Keep it short and simple; do not copy directly from the question!
Effects:


If your function involves mutation, make sure you have an effects
section stating what is being mutated
Examples/Tests:

For examples, make sure to have a base case and a non-base case
at minimum

Of the form: (check-expect (fun_name x1 x2 … xn) expected)
+
Module 1: Review from CS 115
Local

Used to put helper functions within functions
(define (helper x)
...)
(define (main y)
(helper y))
(define (main y)
(local
[(define (helper x) ...)]
(helper y)))
+
Abstract List Functions

Map


map: (X -> Y) (listof X) -> (listof Y)
i.e. map: function lst -> lst




consumes a function and a list
applies that function to every item in the list
produces a list of the same size of lst
use this when you want to change something about every
element in the list
(map func list)
(map sqr (list 1 2 3)) => (list 1 4 9)
+

Filter


filter: (X -> Bool) (listof X) -> (listof X)
i.e. filter: predicate lst -> lst

consumes a function (predicate) and a list

applies that predicate to every item in the list

produces a list that is smaller than or equal to the size of lst

use this when you only want the elements that satisfy a certain
criteria
(filter predicate list)
(filter even?(list 1 2 3 4 5)) => (list 2 4)
+

Foldr

foldr: (X Y -> Y) Y (listof X) -> Y

i.e. foldr: function(that consumes 2 elements) base-case lst
-> result of type Y

consumes a function, a base value, and a list

produces a single result, from applying the function to every
item in the list (starting from the right) as follows
(foldr func base-case list)
(func x1
(func x2
. . .
(func xn base-case))..)
(foldr + 0 (list 1 2 3)) => 6
(foldr + 0 (list 1 2 3))
(+ 1
(+ 2
(+ 3 0)))
+
Module 2: Functional Abstraction

Build-list


build-list: Nat (Nat -> X) -> (listof X)
i.e. build-list: size-of-list function -> list
 consumes a natural number representing the size of the list
being built and a function that is mapped to all values in the
created list
 produces a list from 0 to n-1
 applies the function to all number in the list (just like map!)
(build-list size func)
(build-list 3 sqr)
Part 1: (build-list 3 ...) => (list 0 1 2)
Part 2: (build-list ... sqr) => (list 0 1 4)
So, (build-list 3 sqr) => (list 0 1 4)
+
Lambda


What does lambda do?

lets you write functions without explicitly defining a function

use lambda when the function body is short or when you are
only using it once (i.e. passing it to one bigger function)
Examples from Course Notes:
(define (double k)(* 2 k))
Is the same as:
(define double (lambda (k)(* 2 k)))
Notice this version does not have a function name; we can use lambda here
because the function body is really short
+
(define (first-n-evens n)
(build-list n
(lambda (k)(* 2 k))))
We can use lambda here because the function body is short and it is
only being used once (only passed to build-list)
Format of Lambda
(lambda
(list-of-parameters)
body-of-function)
(lambda (x y)(* x y))
((lambda (x y)(* x y)) 2 4) => 8
+
Functions Produces a Function
We know that (lambda (x)(+ x 5)) will not give us a value since
there is no value for x until we give the function one
If we write ((lambda (x)(+ x 5))3)we will get 8 since we are
giving the value 3 for x
((lambda (x)(+ x 5))3)
=> (+ 3 5))
=> 8
If there are multiple parameters we need to provide the function
with multiple values
((lambda (w x y z)(+ w x y z)) 1 2 4 5)
+

Remember when writing the design recipe for functions that
produce or consume functions, use X’s and Y’s as types!

When writing the produced function use the form
(type(s) consumed by function -> types(s) produced by function)
i.e. adder-maker: Num -> (Num -> Num)
+
Module 3: Accumulative Recursion

What is the difference between structural recursion and
accumulative recursion?

Accumulative recursion updates the answer as it goes, instead of
having pending calculations at the end

The two methods are mathematically equivalent but not
computationally equivalent
Structural Recursion
Accumulative Recursion
(list-sum (list 1 2 3 4))
(list-sum (list 1 2 3 4))
=> (+ 1 (list-sum (list 2 3 4)))
=> (list-sum-acc (list 1 2 3 4) 0)
=> (+ 1 (+ 2 (list-sum (list 3 4))))
=> (+ 1 (+ 2 (+ 3 (list-sum (list 4)))))
=> (+ 1 (+ 2 (+ 3 (+ 4 (list-sum empty)))))
=> (+ 1 (+ 2 (+ 3 (+ 4 (0)))))
=> (+ 1 (+ 2 (+ 3 4)))
=> (+ 1 (+ 2 7))
=> (list-sum-acc (list 2 3 4) (+ 0 1))
=> (list-sum-acc (list 2 3 4) 1)
=> (list-sum-acc (list 3 4) (+ 1 2))
=> (list-sum-acc (list 3 4) 3)
=> (list-sum-acc (list 4) (+ 3 3))
=> (list-sum-acc (list 4) 6)
=> (list-sum-acc empty (+ 6 4))
=> (+ 1 9)
=> (list-sum-acc empty 10)
=> 10
=> 10
+
Template:
(define (acc-fun x)
(local
[(define (helper whats-left ans-so-far ...)
(cond
[(base-case whats-left) ans-so-far]
[else (helper ... (update-whats-left)
... (update-ans-so-far)]))]
(helper initial-whats-left
initial-ans-so-far ...)))
+
Run Time

Find all the functions that will get executed (we do not count
run time of functions that are not executed)

Figure out the run time of those individual functions

Figure out how many recursive calls there are (rounded to
nearest O(1), O(n), O(n2), O(2n)

The total running time: (total running time per step) *
(number of recursive calls)
(define (sum-all numbers)
(cond
[(empty? numbers) 0]
[else (+ (first numbers) (sum-all (rest numbers))))]))
empty? O(1); + O(1); first O(1); rest O(1) => 4 steps => O(1)
# of recursive calls: n + 1 => O(n)
Total run time: O(1) * O(n) => O(n)
+

Abstract list functions are applied to every element in the list

BE CAREFUL: these functions are not always linear

check what is being passed to these abstract functions

The size entry of build-list helps determines run time
(define (f3 n)
(foldr + 0 (list 2 4 6)))
+ O(1)
# of recursive calls for foldr: 4 (since the list is of size 3 + 0) => O(1)
Total run time: O(1) * O(1) = O(1)
(define (f1 n) (build-list n add1))
add1 O(1)
# of recursive calls: n
Total run time: O(1) * n = n
+
Module 4: Mutation
We now have the ability to change values of an identifier
We use (set! v expr) where v is a previously defined identifier
i.e. (define v 9)
Note: the type of v can be anything
where expr is the new value of v, which can also be any type
note: expr is evaluated first and then v is updated
If you have a structure, and you want to change a field, use set-structure-field! instead of set!
Example:
(define name “Sally”)
name => “Sally”
(set! name (string-append name “Jones”))
(set! name “SallyJones”)
name => “SallyJones”
Simplify this first
+
begin

begin allows you to do multiple things at the same time

If you want to set multiple identifiers to different values, and
then multiply these new values together, you would need to
use begin

begin executes the first n-1 expressions, and produces the
value of the last (nth) expression

Example:
(define one 1)
(define two 2)
(define three 3)
(begin
(set! one 4)
(set! two 4)
(set! three 4)
(* one two three))
We should get 64 ( 4 * 4 * 4)
+

But remember that order matters, for example if we have the
same code, in different order we will get:
(define one 1)
(define two 2)
(define three 3)
(begin
(set! one 4)
(set! two 4)
(* one two three)
(set! three 4))
This will produce (void) since a set! expression does not
produce anything (a begin expression only evaluates the last
expression)
+
Testing Mutation

When testing mutation use the form:
(check-expect
(begin
Step 1: set initial values
Step 2: call the function being tested
Step 3: put in a list all the things that
should be checked)
(list values here...))
+

Example from Assignment 4

Testing Q1 (Mutation Diagram)
(check-expect
(begin
;; Step 1: set all values to part-A values
(set! r (void))
(set! s (void))
(set! t (void))
(set! u (void))
(set! v (void))
;; Step 2: call the function
(part-A)
;; Step 3: put in a list all the things that should be tested
(list r s t u v (eq? r s)))
(list ...))
+Module 5: Elementary Programming in Python

We only have Nat, Int, and Float for numbers in Python.
Nat and Int values are exact values, so we can use
check.expect to test them.
Float are inexact values, so we need check.within to test them.

Format for Python:
def fname (p1, p2, …, pN):
statement1
statement2
…
return statementK
+
Local Variables

Local variables can ONLY be used inside the function body.

Example:
def main_fn (x1, …, xN):
a=3
…
return fn_help (v1, v2, …, vn)
def fn_help (y1,y2,…, yN):
if v1 == a:
Error: a is not defined here, we can’t use main
function’s local variable/constants in the helper
…
+
Testing
#Q1T1: description
check.expect(“Q1T1”,
fn_name(v1,…,vN),
expected answer)
#Q2T1: descritption
check.within(“Q2T1”,
fn_name(x1,…xM),
expected answer, tolerance)
abs(actural_answer – value_expected) <= tolerance
+ (define-struct
;;
;;
;;
;;
;;
team (name points played))
A Team is structure (make-team Str Nat Nat)
requires:
name is the name of team
points is the number of points a team has
played is the number of games played
Using abstract list functions, write a function totalgames that consumes a list of team structures, lot
and a number of points p, and produces the total
number of games played by all teams with more
than p points.
+
Use build-list to create the list
(list .1 .01 .001 .0001)
+
Write the function diagonal, which consumes a
natural number n and creates a list of lists where the
diagonal values are 1 and every other value is a 0.
For example,
(diagonal 3) => (list (list 1 0 0)
(list 0 1 0)
(list 0 0 1))
+
Write a function, filter-string that consumes a
string of length 1, s, and produces a function that
consumes a list of strings and produces all of the
strings in that list that start with s.
+
Create an accumulatively recursive function
create-palindrome, which accepts a non-empty
list of symbols, word, and constructs a palindrome
by mirroring the list around the last item.
Thus, if we were to represent the word
(list 'a 'b 'c) and apply make-palindrome,
we would get back the representation of
(list 'a 'b 'c 'b 'a).
a memory diagram for the following code, and determine what values will
+ Draw
be produced.
(define-struct student (name grade))
;; A student is a structure (make-student Str Num)
;; requires: n is the name of the student
;; g is the percentage grade of that student (between 0 and 100).
1)
2)
3)
4)
5)
6)
7)
8)
9)
10)
11)
12)
13)
14)
15)
16)
18)
19)
20)
(define g 100)
(define h g)
(set! g 75)
(define s "Bob")
(define s1 (make-student s g))
(define s2 (make-student s g))
(define s3 s1)
(equal? s1 s2)
(equal? s1 s3)
(eq? s1 s2)
(eq? s1 s3)
(define s4 s1)
(set! s1 (lambda (q) (* q q q)))
(set-student-name! s3 "Jae")
(set-student-grade! s4 (s1 4))
(define s5 (make-student (student-name s4)(student-grade
s3)))
(set-student-name! s4 s2)
(set-student-grade! s4 s1)
(set! g ((student-grade s3) h))
+
A natural number, n, is perfect if the sum of its
positive divisors (up to n-1) is n.
For example, 6 is perfect since 1 + 2 + 3 = 6, and 28
is perfect since 1 + 2 + 4 + 7 + 14 = 28.
In python, write a function perfect that consumes a
natural number, n and produces True if n is a
perfect number, False otherwise.
Download