On this page:
1 Directions for submitting
2 Oveview
3 Deconstructing happiness
4 Dancing on a pinhole
5 All the Smileys
6.12

Exercise 2

Due: Tuesday, July 9, 11:59:59 PM EST.

Implement these exercises with the Beginning Student Language. Require the HtDP2e image library at the top of your definitions:

(require 2htdp/image)

1 Directions for submitting

Please read and follow these intructions carefully. You should submit a single file named ex2.rkt on ELMS. You may submit many times, but each submission should be one file called ex2.rkt. You may lose points for not following these instructions.

Make sure the top of the file contains the following, with your name filled in:
;; Exercise 2
;; Name: ...your name here...

2 Oveview

image

The goal of these exercises is to use the “arithmetic of images,” as provided by the 2htdp/image library, to construct an image that looks like the iconic Smiley, “a stylized representation of a smiling humanoid face that is a part of popular culture worldwide.”

An example of the desired result is given to the right.

This problem can be broken into two sub-problems:
  • construct elements of the smiley (head, eyes, smile)

  • compose those elements to create a smiley

Note: You’re solution doesn’t have to be identical to this one, but it should have all the same essential elements arranged in a similar manner. Your solution should also not involve any copy/pasted images. Everything should be constructed using the operations of 2htdp/image.

3 Deconstructing happiness

Before you begin, open a DrRacket window and actively read the documentation for circle, ellipse, rectangle, beside, overlay, image-height, image-width, and crop.

Actively read means more than just reading; it means reading, writing examples, playing, and experimenting as you go.

The smiley consists of a few distinct parts:

Some of these parts can in turn are constructed out of futher subparts:
  • the eyes consist of two eyes (with space between them): image

  • the smile can be constructed from two circles, overlaying them, and taking the bottom half: image image image

Problem 1: Simple images

Using circle, ellipse, and overlay, write expressions that produce images that look like each of the following:

image, image, image, image, and image.

Problem 2: Image helper functions

To help construct these images, complete the following helper function definitions, which have been stubbed for you:

;; hspace : Number -> Image
;; Create given amount of horizontal space as an image
(check-expect (hspace 10) (rectangle 10 0 "solid" "black"))
(define (hspace x)
  empty-image) ; stub
 
;; bottom-half : Image -> Image
;; Crop an image to just it's bottom half
(check-expect (bottom-half (rectangle 100 60 "solid" "red"))
              (rectangle 100 30 "solid" "red"))
(define (bottom-half i)
  i) ; stub

Now write expressions that produce each of the images show in this lab write-up. You may find hspace and bottom-half useful.

Problem 3: HEAD, EYES, and SMILE

Give three definitions that correctly define the head, eyes, and smile images:

(define HEAD ...)
(define EYES ...)
(define SMILE ...)

Problem 4: RADIUS

Define a constant RADIUS, which determines the radius of the smiley face. Reformulate the definitions of HEAD, EYES, and SMILE in terms of RADIUS.

Use the following proportions to calculate the sizes of the other images:

  • The eyes should have a height of 2/3 * RADIUS, width of 1/3 * RADIUS, and space of 1/3 * RADIUS between them.

  • The smile should be constructed from a black circle that has a radius of 8/10 * RADIUS and a yellow circle that is 9/10 of that quantity.

Make sure that changing the value of RADIUS doesn’t break your program and produces a smiley image that is consistently scaled up or down.

Experiment with different values for RADIUS and observe the results.

4 Dancing on a pinhole

Now it’s time to put the pieces together.

You have already seen how to compose images using operations like above, beside, and overlay, but to construct the smiley, you’ll need more fine-grained control of where the peices line up.

image

The image on the right is the smiley with some guide lines added. Notice that the eyes and smile are centered horizontally. Vertically, the middle of the head is aligned with the top of the smile and bottom of the eyes.

To easily align these images in this way we can use 2htdp/image’s notion of a pinhole.

Actively read the documentation for put-pinhole, center-pinhole, clear-pinhole, and overlay/pinhole.

Problem 5: Pinhole helpers

To help align images, complete the following helper function definitions, which have been stubbed for you:

;; center-top-pinhole : Image -> Image
;; Put pinhole halfway across and at top of given image
(check-expect (center-top-pinhole HEAD)
              (put-pinhole RADIUS 0 HEAD))
(define (center-top-pinhole i)
  i) ; stub
 
;; center-bottom-pinhole : Image -> Image
;; Put pinhole halfway across and at bottom of given image
(check-expect (center-bottom-pinhole HEAD)
              (put-pinhole RADIUS (* 2 RADIUS) HEAD))
(define (center-bottom-pinhole i)
  i) ; stub

Experiment with your helper functions and built-in pinhole operations to produce each of the following images:

image, image, image, image, image, image, image, image, image, and image.

Problem 6: SMILEY

Write an expression that produces the smiley image and define the constant SMILEY to refer to it.
(define SMILEY ...)

Example:
> SMILEY

image

5 All the Smileys

Congratulations! You’ve solved one instance of the Smiley problem. But suppose you wanted to produce two or more Smileys, each with a different radius? For example, maybe you want to make something like this:

image

In some sense, you have a solution to this problem: you can edit the definition of RADIUS and run the program to produce each of the Smileys involved in the image above. The problem with this solution is you need many programs to solve an instance of the problem.

A much better solution would be to have a single program that solves any instance of the problem. To do this, you need a function that can compute a Smiley image in terms of some given value for the radius.

;; smiley : Number -> Image
;; Construct a Smiley of given radius

Examples:
> (smiley 20)

image

> (smiley 40)

image

> (smiley 80)

image

Of course, solving this generalization of the Smiley problem should also solve the particular instance of creating a Smiley of radius RADIUS:

Examples:
> (smiley RADIUS)

image

> SMILEY

image

The definition of smiley is going to be very similar to the definition of SMILEY. In fact, you could start from the following stub:

;; smiley : Number -> Image
;; Construct a Smiley of given radius
(define (smiley r)
  SMILEY) ; stub

The definition, like a broken clock, is sometimes right! In particular, (smiley RADIUS) produces the correct result, but every other input does not.

To see, take a look at your definition of SMILEY, which should involve uses of the constants RADIUS, HEAD, EYES, and SMILE:

(define SMILEY
  (... RADIUS ... HEAD ... EYES ... SMILE ...))

Take the right hand side of this definition and replace SMILEY in the definition of smiley:

;; smiley : Number -> Image
;; Construct a Smiley of given radius
(define (smiley r)
  (... RADIUS ... HEAD ... EYES ... SMILE ...))

Looking at this sketch of the code, it should be clear we want to compute things in terms of r in place of the constant RADIUS. The constants HEAD, EYES, and SMILE are also defined in terms of the constant RADIUS, so want to develop functions:

;; head : Number -> Image
;; Construct a head image for a Smiley of given radius
(define (head r)
  HEAD) ; stub
 
;; eyes : Number -> Image
;; Construct an eyes image for a Smiley of given radius
(define (eyes r)
  EYES) ; stub
 
;; smile : Number -> Image
;; Construct a smile image for a Smiley of given radius
(define (smile r)
  SMILE) ; stub

The correct code for smiley can now be obtained by replacing RADIUS with r, and HEAD with (head r), etc.:

(define (smiley r)
  (... r ... (head r) ... (eyes r) ... (smile r) ...))

You should be able to follow a similar process to obtain correct definitions of head, eyes, and smile. For example, in the case of head, replace HEAD with its definition:

(define (head r)
  (... RADIUS ...))

And replace RADIUS with r:

(define (head r)
  (... r ...))

You can check your work by comparing against known solutions:

Examples:
> (head RADIUS)

image

> HEAD

image

> (eyes RADIUS)

image

> EYES

image

> (smile RADIUS)

image

> SMILE

image

> (smiley RADIUS)

image

> SMILEY

image

And you can cofirm it still works when the radius varies:

Examples:
> (head 20)

image

> (head 40)

image

> (eyes 20)

image

> (eyes 40)

image

> (smile 20)

image

> (smile 40)

image

> (smiley 20)

image

> (smiley 40)

image

Having a function makes it easy to write programs that construct several Smileys of varying sizes:

Example:
> (beside (smiley 20) (smiley 40) (smiley 80))

image

Problem 7: smiley

Complete the following function definitions, which have been stubbed for you:

;; smiley : Number -> Image
;; Construct a smiley image of given radius
(check-expect (smiley RADIUS) SMILEY)
(define (smiley r)
  SMILEY) ; stub
 
;; eyes : Number -> Image
;; Construct an eyes image for a smiley of given radius
(check-expect (eyes RADIUS) EYES)
(define (eyes r)
  EYES) ; stub
 
;; head : Number -> Image
;; Construct a head image for a smiley of given radius
(check-expect (head RADIUS) HEAD)
(define (head r)
  HEAD) ; stub
 
;; smile : Number -> Image
;; Construct a smile image for a smiley of given radius
(check-expect (smile RADIUS) SMILE)
(define (smile r)
  SMILE) ; stub

Problem 8: Smiles

Write an expression that creates an image like the one at the beginning of this subsection.