¿Cómo puedo leer los datos más rápido?
Pregunta
Hmmm ... es un poco difícil de encontrar un método para la lectura / escritura de datos más rápido lo suficiente para ser aceptado en este problema ( https://www.spoj.pl/problems/INTEST/ ) usando F # .
Mi código ( http://paste.ubuntu.com/548748/ ) recibe TLE. ..
Alguna idea de cómo acelerar la lectura de los datos?
Solución
Esta versión de mina pasa el límite de tiempo (pero todavía es terriblemente lento ~ 14 segundos):
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
Aunque el cuello de botella de esta versión es en realidad la conversión string -> uint32
(molde uint32 estándar de cadena es aún más lento) la lectura en sí dura alrededor de 2 segundos (frente a 6 segundos del tiempo total) en mi entrada de la muestra (archivo ~ 100M) - todavía no es un gran resultado. Una vez s2i
se reescribe en estilo imperativo, el tiempo de ejecución total puede reducirse a 10 seg en SPOJ:
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
Otros consejos
No lo sé realmente, pero yo supongo que la lectura de un puesto carácter a la vez es malo, y usted debe leer, por ejemplo, 4k en un tampón a un tiempo y luego procesar el búfer.
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