Lab 2 (80 points)

Download the skeleton file Pi.elm and use it as a starting point for the following problems. Look for all occurrences of TODO in comments, which point out where you should implement your solutions. Once you are done, follow the submission instructions below.

Problem 1: Estimating Pi

In this problem, you will write a program that estimates the value of π. You will also get practice with the basics of programming web applications in Elm by implementing a simple animation — using the Time, Random, and 2D graphics libraries — to accompany the estimation process.

The idea behind estimating π for this problem is simple: throw darts randomly at the unit square and keep track of how many fall within the circle that is centered in the square. According to the areas of circles and squares, the fraction of points within the circle is an estimate of π / 4.

The application will be organized in a familiar way:

main = 
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions

2.1.1 – The “Model” (5 points)

First, we define the following type alias to describe points:

type alias Point = { x:Float, y:Float }

Next, we define the model to keep track of the state the simulation at any given point:

type alias Model =
  { hits : List Point
  , misses : List Point
  , hitCount : Int
  , missCount : Int
  , seed : Seed

The first two components of Model record which points “hit” inside the unit circle, and which points “missed.” We maintain two integer counters for the lengths of these lists, to avoid recomputation. Lastly, we maintain a Random.Seed value that is used to generate the next random point.

Define the initial model; any initial seed value is acceptable.

initialModel : Model

2.1.2 – The “Controller” (45 points)

We need only a dummy “tick” message to trigger the generation of a random Point.

type Msg = Tick

Using the Time library, implement subscriptions to trigger a Tick every so often. Exactly how long (for example, every 100 milliseconds or every 1 second) is up to you.

subscriptions : Model -> Sub Msg

Next, implement the following Random.Generator of Points. Notice how Random provides primitive Generators for base types, which can be used to construct Generators for more complex types, such as Point.

pointGenerator : Generator Point

Finally, implement the update function so that every time a Msg comes in, a Point is randomly generated and the new Model takes into account whether this Point is a hit or miss.

update : Msg -> Model -> (Model, Cmd Msg)

We have not yet discussed commands (i.e. Cmd) in detail, so the second component of the output should always be Cmd.none. When looking into the API of the Random library, make sure to use the “manual” functions for generating random values, rather than the functions that use Cmds.

2.1.3 – The “View” (30 points)

The last key component is to render the current state of the simulation to the screen. For this, implement the function:

view : Model -> Html Msg

Although the particular details are largely up to you, your rendering should:

  1. draw dots for each randomly generated point, using different colors to distinguish hits and misses; and
  2. display the current estimate of π based on these points.

You have two options for drawing 2D graphics:

  1. The evancz/elm-graphics package exposes several modules: the Element library defines an API for laying out text, images, and other Elements (e.g. see toHtml); the Collage library provides tools for defining freeform graphics, comprising shapes, lines, colors, etc (e.g. see collage and circle); and Text for styling text. If you use these libraries, add the following package to your elm-package.json:

    "evancz/elm-graphics": "1.0.1 <= v < 2.0.0"
  2. Alternatively, you can use the Svg library to create SVG graphics with CSS (e.g. see svg and circle).

The choice is up to you. With either approach, you may find it useful to define helper functions, such as the following, for the two subtasks above:

pointsToCircles : Color -> List Point -> List Shape  -- if using elm-graphics
pointsToCircle : String -> List Point -> List Svg    -- if using svg

estimatePi : Model -> Float

For reference, click here to see the output from a sample implementation. Be creative!

2.1.4 (10 extra credit points based on voting)

You will receive full points for the parts above as long as everything is working, no matter how pretty (or ugly) the results are. These last few remaining points are reserved for solutions that are particularly pleasing.

To help get the creative juices flowing, here are some possible ideas for making the animation prettier:

  • Make more recent dots darker than older ones
  • Make the dartboard more colorful
  • Have π appear in the background of the dartboard
  • Use a different shape for the dartboard
  • Vary the size of the board and dots based on window size

In the coming weeks, we will generate a poll based on everyone’s solutions to this problem. You may receive points for this problem based on the results of the voting. More details to follow.

Grading and Submission Instructions

Submit the following two files:

  • The file Pi.elm updated with your changes. You are free to modify these files as you wish, as long as you do not change any type signatures that are provided.

  • A 200-by-200 pixel thumbnail image of your animation called ThumbPi.EXT, where EXT is a standard image format such as png, jpg, or gif. This thumbnail will be used to help generate a gallery on the forthcoming voting page, where each thumbnail will link to the corresponding animation. So you will want to choose an accurate and compelling preview of your animation to entice people to view it.

NOTE: There is no need to submit your elm-package.json file. We will run everyone’s submission with one that includes the evancz/elm-graphics package.

Your solution will be graded using a combination of automated grading scripts and manual review. It is a good idea for you to design some test cases of your own to exercise more sample behaviors than just the ones provided in the writeup. We also reserve the right to take into account the organization and style of your code when assigning grades.

If you are not able to finish all parts of the assignment, make sure that all of your submitted files compile successfully. If not, you risk getting zero points for the assignment. In particular, for each file Foo.elm, make sure that it can be loaded into the Elm REPL

% elm-repl
> import Foo

and that it can be compiled to a standalone HTML file:

% elm-make Foo.elm --output=Foo.html
Successfully generated Foo.html