Functional Problem Solving (CSC 151 2014F) : Labs
Primary: [Front Door] [Schedule] - [Academic Honesty] [Disabilities] [Email] - [FAQ] [Teaching & Learning] [Grading] [Rubric] - [Calendar]
Current: [Assignment] [EBoard] [Lab] [Outline] [Reading]
Sections: [Assignments] [EBoards] [Examples] [Handouts] [Labs] [Outlines] [Readings]
Reference: [Setup] [VM] [Errors] - [Functions A-Z] [Functions By Topic] - [Racket] [Scheme Report (R5RS)] [R6RS] [TSPL4]
Related Courses: [Davis (2013F)] [Rebelsky (2014S)] [Weinman (2014F)]
Misc: [Submit Questions] - [SamR] [Glimmer Labs] [CS@Grinnell] [Grinnell] - [Issue Tracker (Course)]
Summary: In this laboratory, you will explore the use of a variety of forms of anonymous procedures. Our primary focus will be on the use of anonymous procedures and the “drawings as values” model to visualize a variety of functions (the mathematical kind).
Make a copy of anonymous-procedures-lab.rkt
,
which contains some useful code for this lab.
In the code for this lab, there is a value named points
.
a. Explain what that value contains.
b. Check your answer experimentally by rendering that value.
>
(check-drawings points)
In this laboratory, we're going to explore ways to visualize functions
by systematically shifting the values in points
. Hence,
most of our commands will look something like:
>
(check-drawings (map vshift-drawing (map function numbers) points))
Use this form to visualize the functions increment
,
sqrt
, and square
. You should visualize the
three functions separately.
You may notice that the function is “upside-down”, because the GIMP coordinate system is opposite the Cartesian coordinate system. We won't worry about this switch in orientation.
Here's our traditional definition of a function that multiplies its parameter by 5. (We've included a bit more documentation than normal.)
;;; Procedure: ;;; times5 ;;; Parameters: ;;; x, a number ;;; Purpose: ;;; Multiply x by 5 ;;; Produces: ;;; result, a number ;;; Preconditions: ;;; If x is an inexact number, it is no more than one-fifth the highest ;;; inexact number and no less than one-fifth the highest inexact ;;; number. ;;; Postconditions: ;;; result = 5*x, to within machine precision. ;;; result is the same "type" as x. For example, ;;; If x is exact, result is exact. ;;; If x is inexact, result is inexact. ;;; If x is an integer, result is an integer. ;;; If x is complex, result is complex. (define times5 (lambda (x) (* 5 x)))
a. Using the form from the previous exercise, visualize this function.
b. As we noted in the reading, instead of writing times5
for the function, we can write a lambda expression. Fill in the rest of the following to get the same effect as we got in the previous step.
>
(check-drawings (map vshift-drawing (map (lambda (x) ______) numbers) points))
c. Write a similar expression to visualize the function “multiply x by -3”.
d. Write a similar expression to visualize the function “subtract ten from x”.
e. Write a similar expression to visualize the remainder you get when dividing x by 10.
After completing this exercise, you may want to compare your answers to those in the notes.
These lambda expressions are a bit long. As you may recall from
the
reading we can also create simple procedures with left-section
(l-s
) and right-section (r-s
).
a. Predict the results of the following expressions.
> (map (l-s + 10) (iota 20)) > (map (r-s + 10) (iota 20)) > (map (l-s - 10) (iota 20)) > (map (r-s - 10) (iota 20)) > (map (l-s * 10) (iota 20)) > (map (r-s * 10) (iota 20)) > (map (l-s / 10) (iota 20)) > (map (r-s / 10) (iota 20)) > (map (r-s modulo 10) (iota 20))
b. Check your answers experimentally. If any of the results fail to make sense, please discuss them. (You might talk to a classmate, the class mentor, your teacher, or some combination thereof.)
c. Redo parts b, c, d, and e from the previous exercise using sections instead of the lambda expressions. If you have difficulty, you may want to check the notes on this exercise.
d. Go back to the definition of points
and write an
expression to space them out a bit horizontally, multiplying the
values in numbers
by 3 before shifting.
In each of these cases, we've graphed a fairly simple function. What if we want to do something a bit more complex. For example, what if, after computing the square root, we want to “stretch out” the visualization by multiplying by 5? What if we want to first subtract 25 (putting the origin closer to the middle of the screen) and then multiply by 5? What if we want to do some other weird combination of procedures?
The composition procedure, o
, described in
the
reading, helps with all of these problems and more.
As you may recall, (o f g)
is a function that
applies g
and then applies f
.
a. Predict and check the results of the following expressions. You may want to check your prediction for each one before going on to the next.
>
(map (o increment square) (iota 20))
>
(map (o square increment) (iota 20))
>
(map (o increment (l-s * 2)) (iota 20))
>
(map (o (l-s * 2) increment) (iota 20))
>
(map (o (l-s + 10) (l-s * 2)) (iota 20))
>
(map (o (l-s * 2) (r-s modulo 5)) (iota 20))
b. The square root visualiation is somewhat shallow. Let's stretch it out a bit. Write an expression to visualize the function “compute the square root and then multiply by 10”.
c. In contrast, the visualization of the square function is perhaps stretched out too much. Write an expression to visualize the function “square and then divide by 100”.
d. Write an expression to visualize the function “compute the remainder after dividing by 11, and then multiply that remainder by 7”.
e. Write an expression to visualize the function “multiply by five and then compute the remainder after dividing by 11”.
f. Write an expression to visualize the function “divide by 10,
compute the sine (with sin
), and then multiply the result
by 100”.
If you find that you have extra time, you can try one of these extra problems or the explorations below.
Implement your own versions of left-section
and
right-section
. You'll probably need new names for
them, such as my-left-section
.
Implement your own version of compose
. You'll probably need
a new name, such as my-compose
.
Write a function, (constant n)
, that returns a function
that takes any value as input and returns n.
>
(define five (constant 5))
>
(five 1)
5
>
(five "hello")
5
>
(five five)
5
If you happen to finish early, experiment with various compositions and sections of functions. For example, you might try to get a “stairstep” graph by dividing and then rounding.
Here's a simple framework. Anywhere you see underscores, you can
plug in a function, such as (o (r-s mod 256) (r-s * 20))
or (lambda (x) (+ 3 (* x 2)))
.
(define num-points 50) (define numbers (iota num-points)) (define make-color (lambda (n) (irgb (___ n) (___ n) (___ n)))) (define basic-drawing (drawing-group drawing-unit-circle (vshift-drawing 0.5 drawing-unit-square))) (define my-drawing-01 (map recolor-drawing (map (o make-color ___) numbers) ; color (map hshift-drawing (map ___ numbers) ; hshift (map vshift-drawing (map ___ numbers) ; vshift (map hscale-drawing (map ____ numbers) ; hscale (map vscale-drawing (map ___ numbers) ; vscale (make-list num-points basic-drawing)))))))
Here are our solutions to the problems.
b.
>
(check-drawings (map vshift-drawing (map (lambda (x) (* 5 x)) numbers) points))
c.
>
(check-drawings (map vshift-drawing (map (lambda (x) (* -3 x)) numbers) points))
d.
>
(check-drawings (map vshift-drawing (map (lambda (x) (- x 10)) numbers) points))
e.
>
(check-drawings (map drawing-vshift (map (lambda (x) (remainder x 10)) numbers) points))
For part c, we expect something like the following:
>
(check-drawings (map vshift-drawing (map (l-s * 5) numbers) points))
>
(check-drawings (map vshift-drawing (map (l-s - 3) numbers) points))
>
(check-drawings (map vshift-drawing (map (r-s * 10) numbers) points))
>
(check-drawings (map vshift-drawing (map (r-s remainder 10) numbers) points))
For the last of the three, it would also be reasonable to write
>
(check-drawings (map vshift-drawing (map (r-s mod 10) numbers) points))