Cree una prueba de velocidad de mecanografía / medición de CPM

11

Las normas

¡Es hora de construir una prueba de velocidad de mecanografía en el idioma que elija!

1 . Proporciona un archivo con un diccionario de elección (cada 'palabra' debe estar delimitada por una nueva línea). Conéctelo a través de stdino proporcione su nombre como argumento de línea de comando.

una
poder
acerca de
encima
ausencia
...

2 . Elija 10 palabras aleatorias del archivo (no se deben permitir duplicados) e imprímalas de la siguiente manera:

-> directo
-> suelo
-> siguiente
-> cinco
...

3 . ¡Comience a medir el tiempo dedicado de ahora en adelante!

4 . Deje que el usuario escriba las diez palabras lo más rápido posible (finalizó con un retorno de carro). Imprima OKcuando tenga una coincidencia, imprima WRONGcuando tengamos un error de escritura (o la palabra ya se escribió correctamente en esta ejecución).

5 . ¡Detener los relojes! Ahora imprimir el CPM (Caracters por minuto) punto de referencia, que se calcula como sigue: (sum of the characters of the chosen words / time spent typing (seconds)) * 60. Redondee al entero más cercano y reproduzca la siguiente salida (muestra):

-> ¡Has obtenido 344 CPM!

Una muestra de ejecución

-> asentarse
-> lado
-> abierto
-> ministro
-> riesgo
-> color
-> barco
-> mismo
-> tamaño
-> espada
asentar
Okay
lado
Okay
abierto
Okay
# ...................... algunas líneas cortadas ......................
palabra
INCORRECTO
espada
Okay
-> ¡Has obtenido 298 CPM!

El ganador

Este es el código colf, la entrada más corta (en el recuento de caracteres del código fuente) gana, ¡diviértete!

ChristopheD
fuente
44
Creo que el ganador debe ser calificado en parte por la persona con el CPM más alto;)
mellamokb
¿Con qué precisión necesitamos medir el tiempo? ¿Está bien una segunda resolución?
Ilmari Karonen
@Ilmari Karonen: una resolución de un segundo estaría bien para este concurso específico.
ChristopheD

Respuestas:

5

K, 146

Asume un archivo de diccionario llamado 'd' en el directorio de trabajo actual.

{b:+/#:'a:10?_0:`:d;-1"-> ",/:a;s:.z.t;while[#a;$[(,/0:0)~*a;[a:1_a;-1"OK"];-1"WRONG"]];-1"--> You have scored ",($(60000*b)%"i"$.z.t-s)," CPM!";}
tmartin
fuente
Muy agradable y breve, primera entrada Kque he visto (aquí en codegolf.se) ...
ChristopheD
Gracias, todas mis respuestas aquí están en Q o (cada vez más) en K.
tmartin
¡No entiendo por qué esto solo obtuvo un voto positivo (el mío)!
ChristopheD
11

Bash - 217 212 199 196 caracteres

No voy a ganar pero fue divertido

declare -A W
for w in `shuf -n10`;do C+=$w;echo -\> $w;W[$w]=OK;done
SECONDS=0
for((;${#W[*]};));do read r;echo ${W[$r]-WRONG};unset W[$r];done
echo --\> You have scored $((60*${#C}/SECONDS)) CPM!

¡Menos de 200 caracteres ahora!

Toma el archivo de la lista de palabras como argumento Ahora toma la lista de palabras en la entrada estándar. Pégalo en la terminal y presiona ^ D

Sugerencia implementada de manatwork

Geoff Reedy
fuente
1
No voy a ganar, pero fue divertido . Creo lo mismo cuando
publico
1
Puede usar la $SECONDSvariable de shell para simplificar el cálculo del tiempo transcurrido.
manatwork
Puede eliminar 2 caracteres más: 1) la :expansión del parámetro del valor predeterminado; 2) el $frente de SECONDSla evaluación aritmética. En realidad, hay otro personaje adicional, la nueva línea en el archivo.
manatwork
4

Rubí189 178 171 168)

$><<t=['',d=[*$<.lines].sample(10)]*'-> '
s=Time.now
puts d.delete($stdin.gets)?:OK:'WRONG'while d[0]
puts'--> You have scored %i CPM!'%((t.size-40)/(Time.now-s)*60)

Bastante básico, estoy seguro de que hay mejoras por hacer. Toma el nombre de archivo del diccionario como argumento de línea de comandos.

EDITAR : Algunos ajustes menores, principalmente para retener las nuevas líneas del diccionario. Como resultado, el archivo necesitará una nueva línea final para funcionar correctamente.

Paul Prestidge
fuente
4

C, 305 309 347 caracteres

char*stdin,w[11][99];long i,t;main(int n,char**v){v=fopen(v[1],"r");
for(srand(time(&t));fgets(w[i++>9?(n=rand()%i)>10?0:n:i],99,v););
for(i=n=0;i<10;n+=printf("-> %s",w[++i])-4);
for(;i;puts(!strcmp(*w,w[11-i])?--i,"OK":"WRONG"))fgets(*w,99,stdin);
printf("--> You have scored %ld CPM!\n",n*60/(time(0)-t));}

Gracias a @ugoren por las sugerencias de mejora. El uso de una "11ª palabra" para descartar las entradas de diccionario entrantes fue una gran victoria sobre mi enfoque anterior de strcpy-if-elegido.

Aquí está la fuente no protegida:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

static char words[11][99];
static long i, t;

int main(int argc, char *argv[])
{
    FILE *fp;
    int n;

    fp = fopen(argv[1], "r");
    srand(time(0));
    for (i = 0 ; fgets(words[0], sizeof words[0], fp) ; ++i) {
        n = i < 10 ? i : rand() % i;
        if (n < 10)
            strcpy(words[n + 1], words[0]);
    }
    fclose(fp);

    n = 0;
    for (i = 1 ; i <= 10 ; ++i)
        n += printf("-> %s", words[i]) - 4;
    t = time(0);
    i = 1;
    while (i <= 10 && fgets(words[0], sizeof words[0], stdin)) {
        if (strcmp(words[0], words[i])) {
            puts("WRONG");
        } else {
            puts("OK");
            ++i;
        }
    }
    if (i > 9)
        printf("-> You have scored %ld CPM!\n", n * 60 / (time(0) - t));

    return argc - argc;
}
caja de pan
fuente
Algunas mejoras: 1. K & R: declaración main(n,v)char**v;{.... 2. stdinpuede ser char *. fgets(buf,len,stdin)= gets(buf)(no importa los desbordamientos del búfer). 3. ¿Qué tiene de malo rand()%i? RAND_MAXno es necesario 4. ¿Por qué long?
Ugoren
1
También: 1) t=time(0)-> time(&t). 2) n*60/(time(0)-t)tiene paréntesis que deben ir, *60se puede mover a n+=60*printf, entonces n/=time(0)-t. 3) Reemplazar bcon un elemento extra adentro w, reemplazar strcpycon leer directamente en w.
Ugoren
Sustitución fgets()con gets()las necesidades de código adicional para hacer frente a las nuevas líneas en el diccionario; esto terminó siendo más corto. rand()%ino es suficiente El cálculo real es (double)i*rand()/RAND_MAX. Mover el *60a la printf también significa cambiar el -4a -240para que finalmente resulte una pérdida. Sin embargo, sus otros puntos son válidos (creo). Ah, y longes porque el tiempo es tradicionalmente largo. El hecho de que estemos jugando al golf no significa que no podamos ser portátiles.
breadbox
Me perdí 4-> 240... La portabilidad y el golf no van bien juntos. Pero definir i,t;(implícitamente int) está bien hasta MAX_INTsegundos (si no lo usa time(&t)). Con rand()todo lo que necesitas es una 10/ioportunidad, y lo rand()%i<10hace.
Ugoren
Su selección aleatoria es algo defectuosa (no es que se requiera imparcialidad absoluta). La línea 11 debe tener una probabilidad de 10/11 de ser seleccionada, pero usted sí rand()%10>10, lo que le da el 100%. rand()%(i+1)>9es mejor (pero en cambio si %(i+1)hacerlo i++>9?. También moverse *stdinser el primero y ahorra espacio.
ugoren
2

C # 401

void T(){
Action<string>C=Console.WriteLine;Func<string>R=Console.ReadLine;
var w=new List<string>();
for(var l=R();l!="";l=R())w.Add(l);
var s=w.OrderBy(_=>Guid.NewGuid()).Take(10).ToList();
s.ForEach(x=>C("=> "+x));
var t=s.Select(x=>x.Length).Sum();
var c=Stopwatch.StartNew();
while(s.Any()){C(s.Remove(R())?"OK":"WRONG");}
c.Stop();
C("--> You have scored "+c.Elapsed.TotalSeconds*60/t+" CPM!");}

Versión en ejecución aquí: http://ideone.com/Nt6Id

Cristian Lupascu
fuente
2

Python ( 256 235)

import time as t,random as r
def p(x):print x
c=r.sample(input().split("\n"),10)
z=lambda x:p(("WRONG","OK")[raw_input()==x])or len(x)
p("--> "+"\n--> ".join(c))
_=t.time()
p("--> You have scored %d CPM!"%(sum(map(z,c))/(t.time()-_)*60))

Esto está en python 2.x, en 3.x puedo eliminar 4 caracteres más usando la función de impresión.

Nuevas líneas incluidas

Joel Cornett
fuente
2
"Pregunta: ¿Cuentan las nuevas líneas?" Usualmente vamos por "caracteres necesarios". En el caso de Python, sí, las nuevas líneas deben contarse, ya que eliminarlas evitará que el programa funcione.
Joey Adams
1
Creo que puedes cambiar z=lambda x:a def z(x):.
Joey Adams
@JoeyAdams: Podría si solo necesitara devolver ninguno, pero necesito regresar len(x)y def z(x):returnson 5 personajes más: /
Joel Cornett
Creo que puedes ganar algunos personajes ingresando la entrada (permitida en la pregunta) y usando en input()lugar desys.argv[1].read()
ChristopheD
@ JoelCornett: Vaya, tienes razón.
Joey Adams
2

PHP 187 bytes

Se han agregado nuevas líneas para mayor claridad:

<?$s=file($argv[1]);
for(shuffle($s);$i++<10;$l+=strlen($$i))echo~ÒÁß,$$i=$s[$i];
for($t=time();$j++<10;)echo$$j==fgets(STDIN)?OK:WRONG,~õ?>
--> You have scored <?=0|$l/(time()-$t)*60?> CPM!

Acepta el nombre de archivo del diccionario como argumento de línea de comando. El archivo del diccionario debe terminar con una nueva línea.

primo
fuente
2

Scala ( 319 306 304 302)

var s=util.Random.shuffle(io.Source.fromFile(args(0)).getLines.toSet)take 10
def?(a:Any)=println(a)
var l=(0/:s){_+_.size}
s map{"-> "+_}map?
def n=System.nanoTime
val t=n
while(s.size!=0){val m=readLine
if(s contains m)?("OK")else?("WRONG");s-=m}
?("--> You have scored "+l*60000000000L/(n-t)+" CPM!")
Príncipe John Wesley
fuente