These exercises concern streams and delayed evaluation, and provide some practice using them in a remarkable and non-trivial example—computing the decimal digits of π.
Due Tuesday, October 17, 5:00 PM
For this first part of the assignment, you will hand in one file: streams.scm, in your new project directory .../cs450/hw5, with discussion in the same file, as Scheme comments.
This file should begin with some definitions from the textbook, which are included here. You should copy these definitions into the top of your file pi.scm (in addition to any other definitions you might find useful before starting the code for the various problems below). This is important: streams.scm should not load any other file—it should be a self-contained file that contains any code it needs.
If you use DrRacket for development, then you will find that cons-stream is not pre-defined for you. Here's what you do: put the following code at the top of your file:
(define-syntax cons-stream (syntax-rules () ((cons-stream head tail) (cons head (delay tail)))))But please be careful: This code does not work under UMB Scheme. So before you pass your paper in, please comment out this code. Otherwise your entire paper won't work. (In any case, you want to be sure you check your work with UMB Scheme, so if you have forgotten to do this, you will discover it this way.)
Also please note: nowhere in the code for this assignment do you need to use set! or any other operator that changes the value of a variable. Sometimes informally, I write in the paper of "changing the value" of some variable. What that always really means is a recursive call in which the new value is passed. But no variable actually changes its value.
Please be careful about this. The whole point of this assignment is to use streams and recursion. If you read what I have written here carefully and do what I suggest, I think you will be amazed at how simple and clear the code for these procedures is.
(display-n stream n)that prints the first n elements of stream, each on a separate line.
This exercise is pretty simple, provided you follow the suggestion in the book. In fact, you can forget about checking for the empty stream—we will only use this procedure for infinite streams.
After you get this working (and test it), you should answer the following questions:
(stream-map proc (map<
??>
argstreams))))
(apply stream-map proc (map<
??>
argstreams))))
Please note: I'm not asking for answers such as "It works", or "It doesn't work". I'm looking for explanations. And the explanations have to be correct. In the past, I have had students write things that not only were wrong, but that they could easily have seen were wrong if they had just tried them out.
A good answer to this question will take some careful explaining. And what I wrote in an earlier assignment still holds: any explanation you give about how Scheme works has to be based explicitly on the Scheme language definition R5RS. If it isn't, then the explanation is flat-out wrong.
Your answer should be in the form of an extended Scheme comment.
(define ones (cons-stream 1 ones)) (define integers (cons-stream 1 (add-streams ones integers)))
Type in these definitions and verify that they work by using the display-n procedure. Generate the stream notdiv-235 of all integers that are not divisible by any of the numbers 2, 3, or 5. (Use stream-filter.)
Due Tuesday, October 24, 5:00 PM
There are two problems in this part of the assignment. They are both long and difficult. They are based on an expository paper that you will find on my web site: Computing the Digits in π. Actually, all you really need to read in that paper is Section 8, although you may be interested in looking at other parts as well But you will really need to read and understand all of Section 8. (Well, you don't actually have to read the two proofs in Sections 8.1.1 and 8.2.3, but you might want to at least skim those two sections to get an understanding of what is going on.)
Section 8 of the paper is adapted from the paper ``Unbounded Spigot Algorithms for the Digits of Pi'', by Jeremy Gibbons, in the American Mathematical Monthly (Vol. 113, Number 4; April 2006).
As in Part 1 of the assignment, please note that nowhere in the code for this assignment do you need to use set! or any other operator that changes the value of a variable. Sometimes informally, I write in the paper of "changing the value" of some variable. What that always really means is a recursive call in which the new value is passed. But no variable actually changes its value.
Put your code for this part of the assignment in the file pi.scm in your hw5 directory. This file should begin with the same definitions as the file streams.scm from Part 1. pi.scm should not load any other file.
Also, you should create a separate text file notes.txt to hold more extended discussions of the problems and the code you wrote. (Of course, the code should still be commented in place.)
The function mult-stream produces a stream which is the decimal representation of the product of m with the number represented by strm. Don't worry about where the decimal point goes for this assignment. (Of course, in practice that would be very important! It's not at all hard to figure out, but it's not what I'm concerned about right here.)
Somewhere in the course of doing this, you will probably need a function which you might want to name
number->list-of-digitswhich takes a non-negative integer as input and returns the list of single digits that make up the decimal representation of that integer. There are various ways to do this. One way is to use some of the built-in Scheme functions that operate on strings and characters, such as
number->string string->list char->integerIf you do this, please be sure to notice that char->integer returns the ASCII value of a character, so if the character is "3", for instance, what is returned from char->integer is not the number 3. So you'll have to adjust for that as well.
On page 54, just before Section 8.2.1, it is stated that we could have performed the sequence of computations there, but starting with a value different from 2 and still got the same result (in the limit, of course). Do the computations starting with 3 instead of 2 and show that this seems to be true. (This isn't a proof, of course, right?) Put this in notes.txt.
And just to be completely clear about this: when I talk about "starting with 3 instead of 2", I'm talking about replacing only the rightmost 2 in the expressions, not all of them.
Please be careful. I want you to produce a procedure named pi, not a stream named pi. The procedure, when invoked, should produce a stream.
To do this, you will need to have a representation for a 2x2 matrix. A simple list of 4 elements will do. Write a constructor and selectors for this.
You will also need a procedure to multiply matrices. I suggest calling this procedure compose, since the term "multiply" is overloaded enough as it is.
You will need to produce the original input stream. For a hint on how to do this, look at how we produced the stream integers using add-stream. You will need to notice how each element of the stream is produced from the previous one: you just add the matrix
| 1 4 | | | | 0 2 |to each element of the stream to get the next one. (Make sure you understand this.) Just as the stream integers was produced from the initial stream ones, you can build up the stream strm by starting with the stream all of whose elements are this matrix, and you can construct this stream in turn the same way as the stream ones was constructed.
That should enable you to produce strm recursively. (You'll also need a procedure to add matrices. Remember that you add matrices by adding corresponding elements.)
(quotient a b)is just the floor of a/b. Isn't that neat?
Finally, a word about your notes.txt file. I have asked some questions above, and I expect to see the answers in that file. However, if that is all you put in that file, I will be very disappointed. You don't want me to be disappointed. I expect that you will learn a lot by doing this assignment. I expect you to write about that in notes.txt.
Believe it or not, I have occasionally seen things like this:
"I was confused at first. But then I thought about it a lot, and now I understand it."
I hope you understand that this sort of thing is useless. It doesn't tell me or anyone else anything at all. Please spend some serious time making your notes.txt file informative and useful.