如果我期望从用户输入中得到一个用空格分隔的整数字符串(已知预期整数的数量),我可以在haskell Data中传输它。像这样的向量:
main = do
n <- readLn -- this is number of ints
l' <- getLine
let a = (read :: String -> Int) <$> words l'
return $ V.fromList a
但是我想尽快完成, w/o中间列表,在这种情况下,构造Vector的最快方法是什么?
p。我正在考虑循环getChar + replicateM,但不确定它是否会更快。
下面的代码应该非常快。
{-# LANGUAGE BangPatterns #-}
import Data.Char
import qualified Data.Vector.Unboxed as V
import qualified Data.ByteString.Lazy as BL
numbers :: Int -> BL.ByteString -> V.Vector Int
numbers n = V.unfoldrExactN n $ go 0
where go !acc bs = case BL.uncons bs of
Just (c, bs') | c' >= zero && c' <= nine -> go (acc*10+c'-zero) bs'
| otherwise -> (acc, bs')
where c' = fromIntegral c
zero = ord '0'
nine = ord '9'
Nothing -> (acc, BL.empty)
main = do
n <- readLn
inp <- BL.getContents
print $ V.sum (numbers n inp)
注意这个版本没有输入验证。它只解析由单个非数字分隔符分隔的数字,并且会将重复的分隔符误读为额外的零值。
在我的机器上用GHC 8.10.4编译,它每秒处理大约0.5 gb,并且比类似的gcc编译的C版本高出约10%,这有点可疑,但我没有看到我的C版本有任何明显的问题:
#include <stdio.h>
long v[100000000];
int
main()
{
long n;
scanf("%ldn", &n);
for (int i = 0; i < n; ++i) {
long acc = 0;
int c;
while ((c=getchar())>='0')
acc = acc*10+c-'0';
v[i] = acc;
}
long total = 0;
for (int i = 0; i < n; ++i) {
total += v[i];
}
printf("%ldn",total);
return 0;
}