praxis

Various programming exercises.
Log | Files | Refs

commit 690d99a94ea8d9c3fafe97a21fbe5a822e02a26a
parent 9cdb52e7c7113925b6f6b96ae95afb18ad80f4ea
Author: Jared Tobin <jared@jtobin.ca>
Date:   Sun,  8 Jul 2018 17:04:21 +1200

Overengineered exercise thingy.

Diffstat:
A20180601_exercise/Exercise.hs | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A20180601_exercise/grades.dat | 9+++++++++
2 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/20180601_exercise/Exercise.hs b/20180601_exercise/Exercise.hs @@ -0,0 +1,67 @@ +{-# OPTIONS_GHC -Wall -fno-warn-type-defaults #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ViewPatterns #-} + +import qualified Control.Foldl as L +import Data.Char as C +import qualified Data.Foldable as FO +import qualified Data.Map.Strict as MS +import Data.Monoid +import qualified Data.Text as T +import qualified Data.Text.IO as T +import qualified Pipes as P +import qualified Pipes.Prelude as P +import qualified Pipes.Prelude.Text as PT +import System.IO + +data Record = Record { + rnum :: !Int + , rcrs :: !T.Text + , rgra :: !Int + } deriving (Eq, Show) + +parse :: T.Text -> Record +parse (T.strip -> line) = + case T.splitOn "|" line of + [tnum, rcrs, tgra] -> + let rnum = parseNum tnum + rgra = parseNum tgra + + in Record {..} + + _ -> error "parse: bad input" + +parseNum :: T.Text -> Int +parseNum = + snd . T.foldr alg (1, 0) + where + alg char (base, acc) = + let nbase = base * 10 + nacc = acc + C.digitToInt char * base + in (nbase, nacc) + +collect :: L.Fold Record (MS.Map T.Text Record) +collect = L.Fold alg mempty id where + alg acc rnew@(Record nnew cnew _) = + case MS.lookup cnew acc of + Nothing -> MS.insert cnew rnew acc + Just Record {..} -> + if nnew < rnum + then MS.insert rcrs rnew acc + else acc + +render :: Record -> T.Text +render Record {..} = rcrs <> ": " <> (T.pack . show) rgra + +main :: IO () +main = do + file <- openFile "grades.dat" ReadMode + + let handle = PT.fromHandleLn file + pipe = P.for handle (P.yield . parse) + + result <- L.purely P.fold collect pipe + + mapM_ (T.putStrLn . render) (FO.toList result) + diff --git a/20180601_exercise/grades.dat b/20180601_exercise/grades.dat @@ -0,0 +1,9 @@ +22|Data Structures|45 +23|English|52 +22|English|51 +26|Data Structures|72 +23|Data Structures|61 +21|English|81 +19|Biology|83 +31|Biology|95 +8|English|66