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.
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 =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
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
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 Point
s. Notice how Random
provides primitive Generator
s for base types, which can be used to construct Generator
s 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 Cmd
s.
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:
You have two options for drawing 2D graphics:
The evancz/elm-graphics
package exposes several modules: the Element
library defines an API for laying out text, images, and other Element
s (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"
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!
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:
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.
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