Solo Assignment D
-
Dueish: Thu Dec 03. But working with a partner on PS5 has a higher priority than this solo assignment.
-
Notes:
-
This is a solo assignment. You must complete all parts of this assignment entirely on your own without help from any other person and without consulting any resources other than course materials or Racket documentation. You may ask Lyn for clarification, but not for help.
-
You can do all problems on this assignment based on material you learned for PS4. Be sure to study the solutions to PS4 before doing this assignment.
-
This assignment has two solo problems worth 40 solo points.
-
-
How to Start Solo Assignment D
Follow the instructions in the GDoc CS251-F20-T2 Pset Submission Instructions for creating your SOLO-D Google Doc. Put all written answers and a copy of all code into this SOLO-D GDoc.
-
Submission:
- For all parts of all problems, include all answers (including box-and-pointer diagrams and all Racket & SML code) in your SOLO-D GDoc. Please format your Racket & SML function definitions so that they’re easy to read. Format all derivations and code using a fixed-width font (Courier New or Consolas). You use a small font size if that helps.
- For Problem 1 (Diagonal Duples):
- Be sure that all function definitions in
yourAccountName-solo-d-duples.rktalso also appear in your SOLO-D GDoc (so that I can comment on them) - Drop a copy of your
yourAccountName-solo-d-duples.rktin your~/cs251/drop/solo-ddrop folder on cs.wellesley.edu.
- Be sure that all function definitions in
- For Problem 2 (Partial Reverses):
- Include the box-and-pointer diagram from Part a in your SOLO-D GDoc;
- Include the answer to Part b in your SOLO-D GDoc;
- Include the SML functions definitions for Parts c, d, e in your SOLO-D GDoc (so that I can comment on them);
-
Drop a copy of your
~/cs251/sml/solo-d/yourAccountName-partialReverses.smlfile in your~/cs251/drop/solo-ddrop folder oncs.wellesley.eduby executing the following in yourcsenv appliance(replacing all three occurrences ofgdomeby your cs server username):scp -p ~/cs251/sml/solo-d/gdome-partialReverses.sml gdome@cs.wellesley.edu:/students/gdome/cs251/drop/solo-d
1. Diagonal Duples (22 points)
Begin this problem by downloading this starter file solo-d-duples.rkt, which you should rename to yourAccountName-solo-d-duples.rkt. This file contains provided definitions for this solo problem.
This problem concerns one of the provided functions in yourAccountName-solo-d-duples.rkt.
(define (diagonal-duples n) ; Assume is n a nonnegative integer
(foldr append null
(map (λ (sum)
(map (λ (fst) (list fst (- sum fst)))
(range 0 (+ sum 1))))
(range 0 (+ n 1)))))-
(3 points) The
diagonal-duplesfunction generates a list of duples (2-element lists) of integers related to inputn, in a very particular order. Carefully describe in English the output list of duples in terms ofn. As in PS4 Problem 3a, do not describe the Racket code or algorithm that generates the duples. Instead, specify (1) exactly what duples are in the output list (in a general way, not giving examples) and (2) exactly what order the duples are in. Your description must be precise enough that someone else could implement thediagonal-duplesfunction correctly based on your description, without seeing the original Racket definition. (You should carefully study the PS4 Problem 3a solution before answering this part.) -
(5 points) Recall the
genlist-applyfunction from lecture and PS4 (which is supplied as a helper function inyourAccountName-solo-d-duples.rkt).(define (genlist-apply next done? keepDoneValue? seed) (if (apply done? seed) (if keepDoneValue? (list seed) null) (cons seed (genlist-apply next done? keepDoneValue? (apply next seed)))))In the file
yourAccountName-solo-d-duples.rkt, define a Racket functiondiagonal-duples-genlist-applythat has the same input/output behavior asdiagonal-duplesbut is defined usinggenlist-applyby fleshing out the missing expressions denoted by the quoted symbols in the following skeleton:(define (diagonal-duples-genlist-apply n) ; Assume is n a nonnegative integer (genlist-apply 'next-function-goes-here 'done-function-goes-here 'keep-done-value-goes-here 'seed-goes-here ))Note: Carefully study the solution to
pairs-genlist-applyfrom PS4 Problem 3c before beginning this part. -
(6 points) Recall the
iterate-applyfunction from lecture and PS4 (which is supplied as a helper function inyourAccountName-solo-d-duples.rkt):(define (iterate-apply next done? finalize state) (if (apply done? state) (apply finalize state) (iterate-apply next done? finalize (apply next state))))In the file
yourAccountName-solo-d-duples.rkt, define a Racket functiondiagonal-duples-iterate-applythat has the same input/output behavior asdiagonal-duplesbut is defined usingiterate-applyby fleshing out the missing expressions denoted by the quoted symbols in the following skeleton:(define (diagonal-duples-iterate-apply n) ; Assume is n a nonnegative integer (iterate-apply 'next-function-goes-here 'done?-function-goes-here 'finalize-function-goes-here 'initial-state-goes-here ))Notes:
-
Carefully study the solution to
pairs-iterate-applyfrom PS4 Problem 3d before beginning this part. -
Unlike the
diagonal-duples-genlist-applyfunction, which add duples from the front of the list to the end, yourdiagonal-duples-iterate-applyimplementation should add duples from the end of the list to the beginning. -
In this function you should not use
snoc,append, orreverseon any lists. You should only useconsto extend a list. Why? Because repeatedsnocing leads to quadratic running times. How? By constructing the desired output list in reverse, starting with the last duple and working your way back to the first duple. -
As in PS4 Problem 3d, it may be helpful to use iteration tables involving concrete examples to help you define this function.
-
-
(8 points) In the file
yourAccountName-solo-d-duples.rkt, define a tail-recursive Racket functiondiagonal-duples-iterthat has the same input/output behavior asdiagonal-duplesbut is defined iteratively using tail-recursive helper functions.For full credit, your definition should flesh out this exact skeleton with nested function definitions:
(define (diagonal-duples-iter n) ; Assume is n a nonnegative integer (define (outer-tail {outer-parameters}) (define (inner-tail {inner-parameters}) {inner-body}) ; call inner_tail and outer-tail tail-recursively in inner-body {outer-body) ; call inner_tail tail-recursively in outer-body (outer-tail ...)Substantial partial credit can be earned for other iterative solutions that use tail recursion, such as solutions that use a single tail-recursive helper function.
Notes:
-
Carefully study the solution to
pairs-iter-nestedfrom PS4 Problem 3f before beginning this part. -
Unlike the
diagonal-duples-genlist-applyfunction, which add duples from the front of the list to the end, yourdiagonal-duples-iterimplementation should add duples from the end of the list to the beginning (like you did indiagonal-duples-iterate-apply). -
For the same reasons as in
diagonal-duples-iterate-apply, in this function you should not usesnoc,append, orreverseon any lists. -
IMPORTANT: Just naming a function to end in
-taildoes not make it tail recursive! In order to be tail recursive, all calls of your tail recursive functions must not be subexpressions of other function calls. E.g. in the code(if <test> <then> (outer-tail (inner-tail ...) ...))the call to
outer-tailis a tail call, but the the call toinner-tailis not a tail call (because it is a subexpression of another call).
-
2. Partial Reverses (18 points)
Begin this problem via these two steps:
-
Execute the following in a shell in your
csenvappliance to get the~/cs251/sml/solo-ddirectory that contains SML starter code for Parts c, d, and e of this problem:</span>cd ~/cs251/sml git pull origin master -
Make a copy of
partialReverses.smlnamedyourAccountName-partialReverses.sml. You will write your code answers for Parts c, d, and e of this problem inyourAccountName-partialReverses.sml
-
(5 points) Consider the following
partial-reversesfunction in Racket. Draw a box-and-pointer diagram of the list that results from the invocation(partial-reverses '(1 2 3 4)). Use the style of diagram shown in PS2 Problem 2. Study the code carefully and be sure to accurately show all sharing between cons cells in your diagram.(define (partial-reverses xs) (define (partial-reverses-tail ys rev list-rev) (if (null? ys) (cons rev list-rev) (partial-reverses-tail (rest ys) (cons (first ys) rev) (cons rev list-rev) ))) (partial-reverses-tail xs '() '()))Note: As an example of sharing in box-and-pointer diagrams, consider
(define numList '(7 2 4)) (define listOfNumLists (list (append numList (rest numList)) numList (rest numList)))The result has 9 cons cells arranged as follows:

However, if we just enter the printed representation
'((7 2 4 2 4) (7 2 4) (2 4))forlistOfNumLists, that would create 13 cons cells (because in this case there would be no sharing of cons cells):
-
(2 points) How many cons cells would there be in the result of
(partial-reverses (range 1 1001))? -
(5 points) In
yourAccountName-partialReverses.sml, translate the Racket definition ofpartial-reversesinto an SML functionpartialReversesthat has exactly the same behavior (in terms of generating lists with the same sharing).Similar to the
partial-reversesfunction in Racket, the SMLpartialReversesfunction should have a nested function definitionpartialReversesTailthat is called within it.As in PS4 Problem 4, in this and the following parts of this solo problem, do not use
#1,#2, etc. to extract tuple components orList.hd,List.tl, orList.nullto decompose and test lists. Instead, use pattern matching on tuples and lists. -
(4 points) In
yourAccountName-partialReverses.sml, flesh out the following SML skeleton definition ofpartialReversesIterateso that it usesiterateto iteratively calculate the same result (including sharing) aspartialReverses:fun partialReversesIterate xs = iterate (* expression1 *) (* expression2 *) (* expression3 *) (xs, [], [])yourAccountName-partialReverses.smlincludes this definition ofiterate(from PS4 Problem 4b):(* val iterate = fn : ('a -> 'a) -> ('a -> bool) -> ('a -> 'b) -> 'a -> 'b *) fun iterate next isDone finalize state = if isDone state then finalize state else iterate next isDone finalize (next state)Notes:
-
In
yourAccountName-partialReverses.sml, the definition ofiteratemust appear above the defintion ofpartialReversesIterate, which uses it. -
You are allowed use
List.nullor= []or to test for an empty list in this part only.
-
-
(2 Points) In
yourAccountName-partialReverses.sml, flesh out the following skeleton definition ofpartialReversesFoldlso that it usesfoldlto iteratively calculate the same result (including sharing) aspartialReverses:fun partialReversesFoldl xs = foldl (* expression1 *) (* expression2 *) xsRecall that SML’s
foldlfunction has type('a * 'b -> 'b) -> 'b -> 'a list -> 'b.