Last active
November 29, 2019 17:41
-
-
Save AndrewNewcomb/878e0a556f06cc7d25eb to your computer and use it in GitHub Desktop.
Solutions to the F# Koan for AboutTheStockExample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace FSharpKoans | |
open FSharpKoans.Core | |
//--------------------------------------------------------------- | |
// Apply Your Knowledge! | |
// | |
// Below is a list containing comma separated data about | |
// Microsoft's stock prices during March of 2012. Without | |
// modifying the list, programatically find the day with the | |
// greatest variance between the opening and closing price. | |
// | |
// The following functions may be of use: | |
// | |
// abs - takes the absolute value of an argument | |
// | |
// System.Double.Parse - converts a string argument into a | |
// numerical value. | |
// | |
// The following function will convert a comma separated string | |
// into an array of the column values. | |
// | |
// let splitCommas (x:string) = | |
// x.Split([|','|]) | |
//--------------------------------------------------------------- | |
[<Koan(Sort = 15)>] | |
module ``about the stock example`` = | |
let stockData = | |
[ "Date,Open,High,Low,Close,Volume,Adj Close"; | |
"2012-03-30,32.40,32.41,32.04,32.26,31749400,32.26"; | |
"2012-03-29,32.06,32.19,31.81,32.12,37038500,32.12"; | |
"2012-03-28,32.52,32.70,32.04,32.19,41344800,32.19"; | |
"2012-03-27,32.65,32.70,32.40,32.52,36274900,32.52"; | |
"2012-03-26,32.19,32.61,32.15,32.59,36758300,32.59"; | |
"2012-03-23,32.10,32.11,31.72,32.01,35912200,32.01"; | |
"2012-03-22,31.81,32.09,31.79,32.00,31749500,32.00"; | |
"2012-03-21,31.96,32.15,31.82,31.91,37928600,31.91"; | |
"2012-03-20,32.10,32.15,31.74,31.99,41566800,31.99"; | |
"2012-03-19,32.54,32.61,32.15,32.20,44789200,32.20"; | |
"2012-03-16,32.91,32.95,32.50,32.60,65626400,32.60"; | |
"2012-03-15,32.79,32.94,32.58,32.85,49068300,32.85"; | |
"2012-03-14,32.53,32.88,32.49,32.77,41986900,32.77"; | |
"2012-03-13,32.24,32.69,32.15,32.67,48951700,32.67"; | |
"2012-03-12,31.97,32.20,31.82,32.04,34073600,32.04"; | |
"2012-03-09,32.10,32.16,31.92,31.99,34628400,31.99"; | |
"2012-03-08,32.04,32.21,31.90,32.01,36747400,32.01"; | |
"2012-03-07,31.67,31.92,31.53,31.84,34340400,31.84"; | |
"2012-03-06,31.54,31.98,31.49,31.56,51932900,31.56"; | |
"2012-03-05,32.01,32.05,31.62,31.80,45240000,31.80"; | |
"2012-03-02,32.31,32.44,32.00,32.08,47314200,32.08"; | |
"2012-03-01,31.93,32.39,31.85,32.29,77344100,32.29"; | |
"2012-02-29,31.89,32.00,31.61,31.74,59323600,31.74"; ] | |
// Feel free to add extra [<Koan>] members here to write | |
// tests for yourself along the way. You can also try | |
// using the F# Interactive window to check your progress. | |
[<Koan>] | |
let YouGotTheAnswerCorrect() = | |
let splitCommas (x:string) = | |
x.Split([|','|]) | |
let columnNames = splitCommas stockData.Head | |
let columnIndex colName = | |
columnNames | |
|> Array.findIndex (fun x -> x = colName) | |
let idxDate = columnIndex "Date" | |
let idxOpen = columnIndex "Open" | |
let idxClose = columnIndex "Close" | |
// initial solution used a tuple of the date and the price difference | |
let datePriceDiff (dateData: string []) = | |
dateData.[idxDate], abs (System.Double.Parse dateData.[idxClose]) - (System.Double.Parse dateData.[idxOpen]) | |
// First solution was via a Seq | |
let GreatestChange (data: string List) = | |
data.Tail | |
|> Seq.ofList | |
|> Seq.map splitCommas | |
|> Seq.map datePriceDiff | |
|> Seq.maxBy snd | |
|> fst | |
let result = GreatestChange stockData | |
AssertEquality "2012-03-13" result | |
// Second is as a List. Wasn't sure which is idiomatic, Seq or List | |
// Found this... http://stackoverflow.com/questions/10814203/when-to-use-a-sequence-in-f-as-opposed-to-a-list | |
let GreatestChange2 (data: string List) = | |
data.Tail | |
|> List.map splitCommas | |
|> List.map datePriceDiff | |
|> List.maxBy snd | |
|> fst | |
let result2 = GreatestChange stockData | |
AssertEquality "2012-03-13" result2 | |
// Third is without the tuple, which gives one less step to do on each data row | |
let GreatestChange3 (data: string List) = | |
let diff (dateData: string []) = | |
abs (System.Double.Parse dateData.[idxClose]) - (System.Double.Parse dateData.[idxOpen]) | |
let bestRow = | |
data.Tail | |
|> List.map splitCommas | |
|> List.maxBy diff | |
bestRow.[idxDate] | |
let result3 = GreatestChange stockData | |
AssertEquality "2012-03-13" result3 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment