Skip to content

Instantly share code, notes, and snippets.

@derekmorr
Created October 29, 2015 01:12
Show Gist options
  • Save derekmorr/279cbcf39faee07d87b2 to your computer and use it in GitHub Desktop.
Save derekmorr/279cbcf39faee07d87b2 to your computer and use it in GitHub Desktop.
EdX F# class - module 4 (pattern matching)
open System
type GunRecord =
{ xcoord : float
ycoord : float
speed : float
distance : float
name : String }
type GunResult =
| HitTarget of string
| MissTarget of string * float
//takes a csv line and produces a record option
let lineToRecord (line : String) =
let parts = line.Split [|','|]
match parts with
| [| x;y;s;d;n|] ->
try
Some { xcoord = float x; ycoord = float y; speed = float s; distance = float d; name = n }
with
| :? FormatException -> None
| _ -> None
[<Literal>]
let GRAVITY = 9.81
let angleOfReach distance speed = 0.5 * asin((GRAVITY * distance) / (speed * speed))
let angle x y = atan (y / x)
let distanceTravelled speed x y = (speed * speed * sin (2.0 * (angle x y))) / GRAVITY
let hitsTarget (gun : GunRecord) =
let dist = distanceTravelled gun.speed gun.xcoord gun.ycoord
let hitsTarget = dist >= gun.distance
match hitsTarget with
| true ->
HitTarget(gun.name)
| false ->
let neededAngle = angleOfReach gun.distance gun.speed
MissTarget(gun.name, neededAngle)
let readFileData filename =
try
IO.File.ReadLines filename
|> List.ofSeq
|> List.map lineToRecord
|> List.choose (fun e -> id e)
with
| :? IO.IOException as ex ->
printfn "Error reading file: %A" ex.Message
[]
let rad2deg (radians : float) = radians * (180.0/Math.PI)
let printResult gunResult =
match gunResult with
| HitTarget(gunName) ->
printfn "gun %s hit the target!" gunName
| MissTarget(gunName, radians) when Double.IsNaN radians ->
printfn "gun %s missed the target. There is no angle possible to hit the required distance at this speed." gunName
| MissTarget(gunName, radians) ->
printfn "gun %s missed the target. Required angle was %f" gunName (rad2deg radians)
[<EntryPoint>]
let main argv =
printf "Enter a filename: "
let filename = Console.ReadLine()
let gunRecords = readFileData filename
gunRecords |> List.map hitsTarget |> List.map printResult
printfn "Press a key to exit..."
Console.ReadKey()
0 // return an integer exit code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment