4

嗯...找到一种足够快的读取/写入数据的方法以使用F#在这个问题( https://www.spoj.pl/problems/INTEST/ )中被接受,这有点挑战。

我的代码 ( http://paste.ubuntu.com/548748/ ) 得到 TLE ...

任何想法如何加快数据读取?

4

3 回答 3

5

我的这个版本超过了时间限制(但仍然非常慢~14秒):

open System
open System.IO

// need to change standard buffer, not to add an additional one
let stream = new StreamReader(Console.OpenStandardInput(4096))

let stdin = Seq.unfold (fun s -> if s = null then None else Some (s,stream.ReadLine())) <| stream.ReadLine()

let inline s2i (s : string) = Array.fold (fun a d -> a*10u + (uint32 d - uint32 '0') ) 0u <| s.ToCharArray()

let calc = 
    let fl = Seq.head stdin
    let [|_;ks|] = fl.Split(' ')
    let k = uint32 ks
    Seq.fold (fun a s -> if (s2i s) % k = 0u then a+1 else a) 0 <| Seq.skip 1 stdin

printf "%A" calc

尽管此版本的瓶颈实际上是string -> uint32转换(从字符串转换的标准 uint32 甚至更慢),但在我的示例输入(~100M 文件)上读取本身大约需要 2 秒(总时间为 6 秒) - 仍然不是很好结果。一旦s2i以命令式风格重写,在 spoj 上的总运行时间可以减少到 10 秒:

let inline s2i (s : string) =
    let mutable a = 0u
    for i in 0..s.Length-1 do a <- a*10u + uint32 (s.Chars(i)) - uint32 '0'
    a
于 2011-01-01T02:07:48.087 回答
2

我实际上不知道,但我猜想一次读取一个 since 字符是不好的,您应该一次将 4k 读入缓冲区,然后处理该缓冲区。

于 2010-12-30T13:08:09.540 回答
1
let buf =
    let raw = System.Console.OpenStandardInput()
    let bytebuf = new System.IO.BufferedStream(raw)
    new System.IO.StreamReader(bytebuf)

buf.Read()     // retrieves a single character as an int from the buffer
buf.ReadLine() // retrieves a whole line from the buffer
于 2010-12-30T14:19:15.363 回答