-
Notifications
You must be signed in to change notification settings - Fork 2
/
ScannerBS.hs
61 lines (42 loc) · 1.58 KB
/
ScannerBS.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
-- https://byorgey.wordpress.com/2019/10/12/competitive-programming-in-haskell-reading-large-inputs-with-bytestring/
{-# LANGUAGE LambdaCase #-}
module ScannerBS where
import Control.Applicative (liftA2)
import Control.Monad (replicateM)
import Control.Monad.State
import qualified Data.ByteString.Lazy.Char8 as C
import Data.Maybe (fromJust)
type Scanner = State [C.ByteString]
runScanner :: Scanner a -> C.ByteString -> a
runScanner = runScannerWith C.words
runScannerWith :: (C.ByteString -> [C.ByteString]) -> Scanner a -> C.ByteString -> a
runScannerWith t s = evalState s . t
peek :: Scanner C.ByteString
peek = head <$> get
str :: Scanner C.ByteString
str = get >>= \case { s:ss -> put ss >> return s }
int :: Scanner Int
int = (fst . fromJust . C.readInt) <$> str
integer :: Scanner Integer
integer = (read . C.unpack) <$> str
double :: Scanner Double
double = (read . C.unpack) <$> str
decimal :: Int -> Scanner Int
decimal p = (round . ((10^p)*)) <$> double
numberOf :: Scanner a -> Scanner [a]
numberOf s = int >>= flip replicateM s
many :: Scanner a -> Scanner [a]
many s = get >>= \case { [] -> return []; _ -> (:) <$> s <*> many s }
till :: (C.ByteString -> Bool) -> Scanner a -> Scanner [a]
till p s = do
t <- peek
case p t of
True -> return []
False -> (:) <$> s <*> till p s
times :: Int -> Scanner a -> Scanner [a]
times = replicateM
(><) = times
two, three, four :: Scanner a -> Scanner [a]
[two, three, four] = map times [2..4]
pair :: Scanner a -> Scanner b -> Scanner (a,b)
pair = liftA2 (,)