Créez un test de vitesse de frappe / mesure du CPM

11

Les règles

Il est temps de créer un test de vitesse de frappe dans la langue de votre choix!

1 . Vous fournissez un fichier avec un dictionnaire de choix (chaque «mot» qu'il contient doit être délimité par des sauts de ligne). Canalisez-le via stdinou fournissez son nom comme argument de ligne de commande.

une
capable
sur
au dessus de
absence
...

2 . Choisissez 10 mots au hasard dans le fichier (aucun doublon ne doit être autorisé) et imprimez-les de la manière suivante:

-> direct
-> moulu
-> suivant
-> cinq
...

3 . Commencez à mesurer le temps passé à partir de maintenant!

4 . Laissez l'utilisateur saisir les dix mots le plus rapidement possible (terminé par un retour chariot). Imprimez OKlorsque vous avez une correspondance, imprimez WRONGlorsque nous avons une erreur de frappe (ou que le mot a déjà été correctement saisi lors de cette exécution).

5 . Arrêter les pendules! Maintenant imprimer le CPM (par minute caracters) de référence, qui est calculé comme suit: (sum of the characters of the chosen words / time spent typing (seconds)) * 60. Arrondissez à l'entier le plus proche et reproduisez la sortie (exemple) suivante:

-> Vous avez marqué 344 CPM!

Un échantillon

-> s'installer
-> côté
-> ouvert
-> ministre
-> risque
-> couleur
-> bateau
-> pareil
-> taille
-> épée
régler
D'accord
côté
D'accord
ouvert
D'accord
# ...................... quelques lignes coupées ......................
mot
FAUX
épée
D'accord
-> Vous avez marqué 298 CPM!

Le gagnant

C'est le code colf, l'entrée la plus courte (en nombre de caractères du code source) gagne, amusez-vous!

ChristopheD
la source
4
Je pense que le vainqueur devrait en partie être marqué par la personne avec le CPM le plus élevé;)
mellamokb
Avec quelle précision devons-nous mesurer le temps? Une seconde résolution est-elle OK?
Ilmari Karonen
@Ilmari Karonen: une résolution d'une seconde serait très bien pour ce concours spécifique.
ChristopheD

Réponses:

5

K, 146

Suppose un fichier de dictionnaire appelé «d» dans le répertoire de travail actuel.

{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
la source
Très joli et bref, première entrée dans KJ'ai vu (ici sur codegolf.se) ...
ChristopheD
Merci, toutes mes réponses ici sont en Q ou (de plus en plus) en K.
tmartin
Je ne comprends pas très bien pourquoi cela n'a obtenu qu'un seul vote positif (le mien)!
ChristopheD
11

Bash - 217 212 199 196 caractères

Je ne vais pas gagner mais c'était amusant

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!

Moins de 200 caractères maintenant!

Prend le fichier de liste de mots comme argument Prend maintenant la liste de mots sur l'entrée standard. Collez-le dans le terminal et appuyez sur ^ D

Suggestion mise en œuvre à partir de manatwork

Geoff Reedy
la source
1
Je ne vais pas gagner mais c'était amusant - je pense la même chose quand je poste mes solutions C # :)
Cristian Lupascu
1
Vous pouvez utiliser la $SECONDSvariable shell pour simplifier le calcul du temps écoulé.
manatwork
Vous pouvez supprimer 2 autres caractères: 1) l' :expansion du paramètre de valeur par défaut; 2) le $devant de SECONDSl'évaluation arithmétique. En fait, il y a un autre caractère supplémentaire, la nouvelle ligne au et du fichier.
manatwork
4

Ruby (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)

Assez basique, je suis sûr qu'il y a des améliorations à apporter. Prend le nom de fichier du dictionnaire comme argument de ligne de commande.

EDIT : quelques ajustements mineurs, principalement autour de la conservation des nouvelles lignes du dictionnaire. Par conséquent, le fichier aura besoin d'une nouvelle ligne de fin pour fonctionner correctement.

Paul Prestidge
la source
4

C, 305 309 347 caractères

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));}

Merci à @ugoren pour les conseils d'amélioration. L'utilisation d'un "11ème mot" pour éliminer les entrées de dictionnaire entrantes a été une grande victoire par rapport à mon approche précédente strcpy-si-choisie.

Voici la source non golfée:

#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;
}
boite à pain
la source
Quelques améliorations: 1. K & R: déclaration main(n,v)char**v;{.... 2. stdinpeut l'être char *. fgets(buf,len,stdin)= gets(buf)(sans parler des dépassements de tampon). 3. Qu'est-ce qui ne va pas rand()%i? RAND_MAXn'est pas nécessaire. 4. Pourquoi long?
ugoren
1
Aussi: 1) t=time(0)-> time(&t). 2) n*60/(time(0)-t)a entre parenthèses qui doit aller - *60peut être déplacé vers n+=60*printf, puis n/=time(0)-t. 3) Remplacer bpar un élément supplémentaire dans w, remplacer strcpypar lire directement dans w.
ugoren
Remplacer fgets()par gets()du code supplémentaire a besoin de gérer les sauts de ligne dans le dictionnaire; cette fin étant plus courte. rand()%in'est pas suffisant; le calcul réel est (double)i*rand()/RAND_MAX. Déplacer le *60vers le printf signifie également changer le -4vers -240pour qu'il finisse par perdre. Vos autres points sont valables, cependant (je crois). Oh, et longc'est parce que time_t est traditionnellement long. Ce n'est pas parce que nous jouons au golf que nous ne pouvons pas être portables.
boîte à pain
J'ai raté 4-> 240... La portabilité et le golf ne vont pas bien ensemble. Mais la définition i,t;(implicitement int) est OK jusqu'à MAX_INTquelques secondes (si vous n'utilisez pas time(&t)). Avec rand(), tout ce dont vous avez besoin est une 10/ichance, et le rand()%i<10fait.
ugoren
Votre sélection aléatoire est quelque peu imparfaite (pas qu'une équité absolue soit requise). La 11e ligne devrait avoir une chance de 10/11 d'être sélectionnée, mais vous le faites rand()%10>10, ce qui lui donne 100%. rand()%(i+1)>9c'est mieux (mais à la place si c'est le %(i+1)cas i++>9?. *stdin
Déplacez-
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!");}

Version en cours d'exécution ici: http://ideone.com/Nt6Id

Cristian Lupascu
la source
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))

C'est en python 2.x, en 3.x je peux raser 4 caractères supplémentaires en utilisant la fonction d'impression.

Newlines inclus

Joel Cornett
la source
2
"Question: les sauts de ligne comptent-ils?" Nous utilisons généralement les «caractères nécessaires». Dans le cas de Python, oui, les sauts de ligne doivent être comptés, car les supprimer empêchera le programme de fonctionner.
Joey Adams
1
Je pense que vous pouvez changer z=lambda x:pour def z(x):.
Joey Adams
@JoeyAdams: Je pourrais si seulement besoin d'en retourner aucun, mais je dois y retourner len(x)et il def z(x):returny a 5 autres caractères: /
Joel Cornett
Je pense que vous pouvez gagner des personnages en canalisant l'entrée (autorisé dans la question) et en utilisant à la input()place desys.argv[1].read()
ChristopheD
@JoelCornett: Oups, vous avez raison.
Joey Adams
2

PHP 187 octets

Des nouvelles lignes ont été ajoutées pour plus de clarté:

<?$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!

Accepte le nom de fichier du dictionnaire comme argument de ligne de commande. Le fichier de dictionnaire doit se terminer par une nouvelle ligne.

primo
la source
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!")
Prince John Wesley
la source