Programming performance/JCAB Haskell

From HaskellWiki
Jump to navigation Jump to search
  • Language: Haskell
  • Skill: Intermediate. I don't use Haskell much, and I keep going back to the library documentation for the simplest of functions, but I believe I understand many of the scaries aspects of the language.
  • Time: Approx 50 minutes.
  • Notes: This is a bit of let-overkill, but to me it makes sense this way. I didn't see any of the other submissions prior to doing this. I used Visual Haskell for development. I needed two iterations (silly bugs!). I get 13754.97774 as the answer, which sounds more-or-less right (37% gain). It would be nice to know the (a?) correct answer ahead of time, so we know when we got the program right. The problem wasn't very clearly described, IMHO.

Code

module Main where

programmingPerformance file =
    let filteredFile = filter filterLine (lines file)
        filterLine [] = False
        filterLine ('#':_) = False
        filterLine _ = True
        
        closingList = reverse (map extractClosing filteredFile) :: [Double]
        extractClosing line = read ((tokenize line) !! 6)
        tokenize [] = []
        tokenize line = let (token, rest) = getToken line in token : tokenize rest
        getToken []       = ("", [])
        getToken (' ':xs) = ("", xs)
        getToken (x  :xs) = let (token, rest) = getToken xs in (x:token, rest)
        
        result = parseClosingSell 10000.0 [] closingList
        parseClosingSell :: Double -> [(Double, Double)] -> [Double] -> Double
        parseClosingSell cash shares c@(_:y:rest) =
            let (sale, remShares) = foldr maybeSell (0, []) shares
                maybeSell (shClosing, shNum) (accCash, accShares) | (y - shClosing) >= shClosing * 0.06 = (accCash + y * shNum, accShares)
                maybeSell sh                 (accCash, accShares)                                       = (accCash            , sh:accShares)
            in parseClosingBuy (cash + sale) remShares c
        parseClosingSell cash shares [y] =
            let sale = foldr sell 0 shares
                sell (shClosing, shNum) accCash = accCash + y * shNum
            in cash + sale
        parseClosingBuy cash shares (x:y:rest) | (x - y) >= x * 0.03 = parseClosingSell (cash * 0.90) ((y, cash*0.10 / y):shares) (y:rest)
        parseClosingBuy cash shares (x:rest) = parseClosingSell cash shares rest
        
    in result

main = do
    file <- readFile "C:\\JCAB\\ProgrammingPerformance\\gspc.txt"
    let result = programmingPerformance file
    print result