Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
Com S 342 --- Principles of Programming Languages
HOMEWORK 5: RECURSION OVER DATA DESCRIBED BY GRAMMARS AND TAIL RECURSION
Due: by 2:00pm Thursday, Mar 5, 2009 in Computer Science Front Office;
In this homework, you will learn more about recursion over data
described by more complex grammars and about tail recursion.
PRELIMINARIES
1. Download, unzip and install the typedscm library from:
http://www.cs.iastate.edu/~cs342/homework/typedscm.zip
in the collects directory of your PLT scheme installation.
As a result of this step you should have a directory
collects/typedscm. To test if this has worked correctly
type the following in your interpreter.
(require (lib "typedscm.ss" "typedscm"))
TypedSCM is a typed dialect for Scheme made available by
Professor Gary T. Leavens from University of Central
Florida and his students. More information about this
dialect is available from the following web-page.
http://www.eecs.ucf.edu/~leavens/typedscm/
2. Download and add the following modules to your lib342
directory as instructed in HW1, question 4.
http://www.cs.iastate.edu/~cs342/homework/all-mod.scm
http://www.cs.iastate.edu/~cs342/homework/window-layout-mod.scm
http://www.cs.iastate.edu/~cs342/homework/bexp-mod.scm
INSTRUCTIONS
All code is to be written in Scheme, using the exact procedure names
specified in the problem descriptions. Test using your own tests and
also use the examples that we provide as test cases. For coding
problems hand in:
- a printout of the code, and
- if our examples reveals any errors with your code for that problem,
then include a transcript showing a run of our tests.
That is, you only have to hand in output of your testing if it reveals
problems in your code (that you have not fixed). We expect you to run
our examples for each problem, but since the output in the case where the
tests all pass is not very interesting, we will trust you to have done
this. However, you must hand in a transcript of your testing if your
code does *not* pass our tests perfectly, as this will alert us to the
problem and will help us assign partial credit. If we find that your
code is not correct and the problem would have been revealed by our
examples, but you did not hand in test results showing
these problems, then you will receive 0 points for that problem.
You may also hand in a transcript that includes our examples if you wish.
The section headings below give the readings related to the problems.
(Please read them!)
ESSENTIALS OF PROGRAMMING LANGUAGES: SECTION 1.2
THE LITTLE SCHEMER, CHAPTER 5
In these problems, you are not to use the parse-... procedures in your
own code, but you should use the other helpers given in the files
described. The reason for this is that parsing is considered an
expensive operation, and once done once, shouldn't be done internally
in your code. Instead of using the parsing procedures in your code,
use the constructor procedures. We have tried to illustrate how to
use the constructor procedures in many of the examples.
Don't hesitate to write additional helping procedures,
especially for recursion over the lists that are implicit in the use
of Kleene star (*) in various grammars.
------------------------------------------------------------------------
WINDOW LAYOUT
------------------------------------------------------------------------
Suppose we want to descibe how windows are layed out in a window manager.
For the purposes of problems 1 and 2, we will use the following grammar
to describe these layouts. Informally, a window-lay out is a window
or a horizontal layout of 0 or more window layouts or a verticle
layout of of 0 or more window layouts. Window layouts follow the grammar
below:
::=
(window )
| (horizontal {}*
| (verticle {}*
Notice that this is a recursively defined grammar. We have provided a
representation of this data type in the file "window-layout-mod.scm"
which contains many helper procedures for processing layouts.
Useful helpers:
;; type predicate
( window-layout? (type-predicate-for window-layout))
;; case testers (discriminators)
( window? (-> (window-layout) boolean))
( horizontal? (-> (window-layout) boolean))
( vertical? (-> (window-layout) boolean))
;; constructors
( window (-> (symbol number number) window-layout))
( horizontal (-> ((list-of window-layout)) window-layout))
( vertical (-> ((list-of window-layout)) window-layout))
;; observers
( window->name (-> (window-layout) symbol))
( window->width (-> (window-layout) number))
( window->height (-> (window-layout) number))
( horizontal->subwindows (-> (window-layout) (list-of window-layout)))
( vertical->subwindows (-> (window-layout) (list-of window-layout)))
1. (30 points) [smallest-width]
smallest-width : (-> (window-layout) number)
such that (smallest-width layout) returns the largest width of any
window found in layout. If the layout has no windows, the result
should be zero.
You can assume that the input window layout has been constructed
according to the grammar. That is, you don't have to check for
errors in the input, and can assume that the input has been parsed.
(smallest-width (parse-window-layout '(horizontal )))
==> 0
(smallest-width (parse-window-layout '(vertical )))
==> 0
(smallest-width (parse-window-layout '(window simpsons 30 40)))
==> 30
(smallest-width (parse-window-layout '(window family-guy 70 11)))
==> 70
(smallest-width
(parse-window-layout '(horizontal (window family-guy 30 15)
(window futurama 89 55))))
==> 30
(smallest-width
(parse-window-layout
'(vertical
(vertical (window simpsons 200 150))
(horizontal (horizontal (window news 50 5)))
(horizontal (window family-guy 30 15)
(window futurama 89 55)))))
==> 30
You must use the helping procedures in window-layout-mod.scm
in your solution. You can load these into your solution using the
following in your file:
(require (lib "window-layout-mod.scm" "lib342"))
2. (20 points) [grow-by]
This is a problem about the window layouts discussed above.
Write a procedure
grow-by : (-> (number number window-layout) window-layout)
such that (grow-bywidth height wl) returns a window layout that
is just like wl, except that each window in wl is made to have
width w+new and height h+new.
You can assume that the input window layout has been constructed
according to the grammar. That is, you don't have to check for
errors in the input, and can assume that the input has been parsed.
However, to better show how the helping procedures in
window-layout-mod.scm work, in the examples below, we often
use the helping procedures directly to construct window layouts.
(grow-by 10 39 (parse-window-layout '(vertical )))
==> (vertical)
(grow-by 10 39 (parse-window-layout '(horizontal )))
==> (horizontal)
(grow-by 10 39 (parse-window-layout '(window simpsons 30 40)))
==> (window simpsons 40 79)
(grow-by 80 5 (window 'family-guy 30 11))
==> (window family-guy 110 16)
(grow-by 20 30 (horizontal
(list (window 'family-guy 30 15)
(window 'futurama 89 55))))
==> (horizontal (window family-guy 50 45)
(window futurama 109 85))
(grow-by 20 30 (vertical
(list (vertical (list (window 'simpsons 200 150)))
(horizontal
(list
(horizontal (list (window 'news 5 5)))))
(horizontal
(list (window 'family-guy 30 15)
(window 'futurama 89 55))))))
==> (vertical
(vertical (window simpsons 220 180))
(horizontal (horizontal (window news 25 35)))
(horizontal (window family-guy 50 45) (window futurama 109 85)))
You must use the helping procedures in window-layout-mod.scm
in your solution. You can load these into your solution using:
(require (lib "window-layout-mod.scm" "lib342"))
------------------------------------------------------------------------
BOOLEAN EXPRESSIONS
------------------------------------------------------------------------
Let the following be the grammar that describes boolean expressions and
operators for those expressions.
::=
| (and )
| (or )
| (not )
::= P
| Q
Note: the varref used (P or Q) will affect how the boolean expression is
evaluated. We have provided a representation of this data type in the
file "bexp-mod.scm" which contains many helper procedures for processing
boolean expressions and operators.
Useful Helpers:
;; type predicate
( bexp? (type-predicate-for bexp))
( varref? (type-predicate-for varref))
;; case testers (discriminators)
( var-exp? (-> (bexp) boolean))
( and-exp? (-> (bexp) boolean))
( or-exp? (-> (bexp) boolean))
( not-exp? (-> (bexp) boolean))
( P? (-> (varref) boolean))
( Q? (-> (varref) boolean))
;; constructors
( var-exp (-> (varref) bexp))
( and-exp (-> (bexp bexp) bexp))
( or-exp (-> (bexp bexp) bexp))
( not-exp (-> (bexp) bexp))
( P (-> () varref))
( Q (-> () varref))
;; observers
( var-exp->varref (-> (bexp) varref))
( and-exp->left (-> (bexp) bexp))
( and-exp->right (-> (bexp) bexp))
( or-exp->left (-> (bexp) bexp))
( or-exp->right (-> (bexp) bexp))
( not-exp->arg (-> (bexp) bexp))
3. (20 points) [beval]
Write a procedure
beval : (-> (bexp boolean boolean) boolean)
such that (beval bexp p-val q-val) returns the value for bexp when
P has the value p-val and Q has the value q-val.
You are to write this without using Scheme's eval function.
You can assume that the input bexp has been constructed
according to the grammar. That is, you don't have to check for
errors in the input, and can assume that the input has been parsed.
The following are examples.
(beval (parse-bexp 'P) #t #f) ==> #t
(beval (parse-bexp 'Q) #t #f) ==> #f
(beval (parse-bexp '(not P)) #t #f) ==> #f
(beval (parse-bexp '(or (not P) Q)) #t #f) ==> #f
(beval (parse-bexp '(and P (or Q (not Q)))) #t #f) ==> #t
(beval (parse-bexp '(and (or P P) (or (or P P) (or Q Q)))) #f #t)
==> #f
(beval (parse-bexp '(and (or P P) (or (or P P) (or Q Q)))) #t #f)
==> #t
(beval (parse-bexp '(or (not (and P P))
(and (not (not (and P P)))
(not (and P Q))))) #t #f)
==> #t
You must use the helping procedures in bexp-mod.scm
in your solution. You can load these into your solution using:
(require (lib "bexp-mod.scm" "lib342"))
Note that in DrScheme, procedure names in modules seem to be case
sensitive. So be sure to use the names P?, Q?, P, and Q in your
code in upper case.