Homework 8

This homework is a simplified version of this nifty assignment. First read through Ben Stephenson's description for the nifty background. But if you think my assignments are cryptic, try deciphering his details. I originally meant to faithfully recreate his instructions, but somewhere on the way, I lost the will to live.

So, here is a somewhat simplified version of his algorithm. We'll do it in Racket, of course.

  1. To make a w by h blue rectangle with a black outline, use this:
    (cc-superimpose (colorize (filled-rectangle w h) "blue") (rectangle w h))
    
  2. No mutations! That means, we'll use the same technique as he does, passing in a list of random numbers. Each time you need a random number, consume the head, and pass on the tail to the rest of the computation.
  3. Implement a linear congruential generator, in which random numbers are produced by the sequence xn + 1 = (a xn + b) mod m . Good values are a = 1664525, b = 1013904223, and m = 4294967296, but for testing out your code you may want to use something much simpler. Write a function randoms that takes a seed value and a length, producing a list of random numbers between 0 and 1 (i.e., divide xn by m). The first element of the list should be the seed divided by m.
  4. Given a small rectangle with width w and height h inside a big rectangle with dimensions width by height, and a random number r between 0 and 1, we say that the small rectangle is
    1. wide enough if w > 50 and w / width > 0.5 * r
    2. tall enough if h > 50 and h / height > 0.5 * r
    3. big enough if it is both wide enough and tall enough
    The random factor makes it so that most, but not all sizeable rectangles split. I settled on the values 50 and 0.5 after a few experiments.
  5. If a given rectangle is big enough (relative to the original rectangle, not its parent), split it horizontally and vertically in four smaller rectangles. Otherwise, if it is wide enough, split it vertically in two rectangles. Otherwise, if it is tall enough, split it horizontally in two rectangles. In all three cases, recursively process the children. If none of the cases apply, color the rectangle at random. IMPORTANT Consume one random number for deciding whether the rectangle is big/wide/tall enough (even if the rectangle is smaller than 50 by 50). If the rectangle is big enough, consume two random numbers for the line splits. Otherwise consume one random number for the line split or color.
  6. Use the same randomization strategies as Stephenson for splitting and coloring. The split line is randomly chosen between 1/3 and 2/3 of the width or height. The color is randomly chosen as in the middle of page 2 of his handout. (But use primary blue, as Mondrian would have, not sky blue.)
  7. Implement a function (mondrian width height rands) that receives the dimensions and a (sufficiently long) list of random numbers and returns a list of length 2. The first element is the Mondrian painting (nested hc-append, vc-append, cc-superimpose). The second element is the un-consumed tail of the random numbers. You can use (list ... ...) to make this list and first/second to take it apart.
  8. You do not do the extra credit part.
  9. Testing tip: You can choose the dimensions and random numbers to serve your purpose. For example, suppose you want to test the colorization only. Call (mondrian 40 40 '(0.5 0.07 0.42)), and you should get back a red square and a list containing the unused 0.42.
  10. I used only the following Racket constructs in my solution:
    define let let* letrec lambda first second rest list map cond else and modulo + - * / = >
    Ask on Piazza if you feel the need to use anything else.
  11. Use at least ten helper functions in your solution! Because some helper functions refer to the parameters of the original rectangle, you need to define them with a letrec:
    (define (mondrian width height rands)
      (letrec (
               (wide-enough (lambda (w r) (and (> w 50) (> (/ w width) (* 0.5 r)))))
               ...
               (mondrian-helper (lambda (...) ...)))
      (mondrian-helper ...)))
    
  12. You submit