module HOPS.OEIS
(
URL
, ANum (..)
, Sequence
, packANum
, parseStripped
, parseIntegerSeq
, aNumInt
, tag
) where
import Data.List
import Data.Maybe
import Data.Monoid
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import Data.Text.Encoding (encodeUtf8, decodeUtf8)
import Data.Aeson
import qualified Data.Attoparsec.ByteString as A
import Data.Attoparsec.ByteString.Char8
import Control.Monad
import HOPS.Utils.Parse
type Sequence = [Rational]
type URL = String
newtype ANum = ANum {unANum :: Int} deriving (Eq, Ord, Show)
instance ToJSON ANum where
toJSON m = String ("A" <> decodeUtf8 (packANum m))
instance FromJSON ANum where
parseJSON (String s) = pure $ parseANumErr (encodeUtf8 s)
parseJSON _ = mzero
spc :: Parser Char
spc = char ' '
packANum :: ANum -> ByteString
packANum = B.pack . show . unANum
aNum :: Parser ANum
aNum = ANum <$> (char 'A' *> decimal)
parseANum :: ByteString -> Maybe ANum
parseANum = parse_ (aNum <* endOfInput)
parseANumErr :: ByteString -> ANum
parseANumErr = fromMaybe (error "error parsing A-number") . parseANum
dropHeader :: [ByteString] -> [ByteString]
dropHeader = dropWhile (\line -> B.head line == '#')
parseRecords :: ByteString -> [(ANum, ByteString)]
parseRecords = mapMaybe (parse_ record) . dropHeader . B.lines
where
record = (,) <$> (aNum <* spc) <*> A.takeByteString
parseStripped :: ByteString -> [(ANum, Sequence)]
parseStripped bs =
[ (anum, parseIntegerSeq (B.drop 1 s))
| (anum, s) <- parseRecords bs
]
parseIntegerSeq :: ByteString -> Sequence
parseIntegerSeq =
unfoldr (fmap (\(i, bs) -> (fromIntegral i, B.drop 1 bs)) . B.readInteger)
aNumInt :: Parser Int
aNumInt = char 'A' >> decimal
tag :: Parser Int
tag = string "TAG" >> decimal