Zbuduj test szybkości pisania / pomiaru CPM

11

Zasady

Czas zbudować test szybkości pisania w wybranym języku!

1 . Udostępniasz plik z wybranym słownikiem (każde „słowo” musi być oddzielone znakiem nowej linii). Podaj go przez stdinlub podaj jego nazwę jako argument wiersza poleceń.

za
zdolny
o
powyżej
brak
...

2 . Wybierz 10 losowych słów z pliku (duplikaty nie mogą być dozwolone) i wydrukuj je w następujący sposób:

-> bezpośrednie
-> ziemia
-> dalej
-> pięć
...

3 . Zacznij mierzyć czas od teraz!

4 . Pozwól użytkownikowi wpisać wszystkie dziesięć słów tak szybko, jak to możliwe (zakończone znakiem powrotu karetki). Drukuj, OKgdy masz dopasowanie, drukuj, WRONGgdy mamy błąd w pisaniu (lub słowo zostało już pomyślnie wpisane w tym przebiegu).

5 . Zatrzymaj zegary! Teraz wydrukować CPM (caracters na minutę) odniesienia, która jest obliczana w następujący sposób: (sum of the characters of the chosen words / time spent typing (seconds)) * 60. Zaokrąglij do najbliższej liczby całkowitej i odtwórz następujące (przykładowe) wyjście:

-> Zdobyłeś 344 CPM!

Przykładowy przebieg

-> osiedlić się
-> strona
-> otwórz
-> minister
-> ryzyko
-> kolor
-> statek
-> takie same
-> rozmiar
-> miecz
rozstrzygać
dobrze
bok
dobrze
otwarty
dobrze
# ...................... niektóre linie zostały przycięte ......................
słowo
ŹLE
miecz
dobrze
-> Zdobyłeś 298 CPM!

Zwycięzca

To jest colf, wygrywa najkrótszy wpis (w liczbie znaków kodu źródłowego), baw się dobrze!

ChristopheD
źródło
4
Myślę, że zwycięzca powinien zostać częściowo
oceniony
Jak dokładnie musimy mierzyć czas? Czy jedna sekunda jest w porządku?
Ilmari Karonen,
@Ilmari Karonen: w tym konkretnym konkursie wystarczy jedna sekunda.
ChristopheD

Odpowiedzi:

5

K, 146

Zakłada plik słownika o nazwie „d” w bieżącym katalogu roboczym.

{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!";}
tartin
źródło
Bardzo ładny i krótki, pierwszy wpis w Kktórym widziałem (tutaj na codegolf.se) ...
ChristopheD
Dzięki, wszystkie moje odpowiedzi tutaj są w Q lub (coraz częściej) w K.
tmartin
Nie bardzo rozumiem, dlaczego otrzymałem tylko jedną opinię (moje)!
ChristopheD
11

Bash - 217 212 199 196 znaków

Nie wygra, ale było fajnie

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!

Poniżej 200 znaków!

Pobiera plik listy słów jako argument Teraz pobiera listę słów na standardowe wejście. Wklej go w terminalu i naciśnij ^ D

Wdrożono sugestię z manatwork

Geoff Reedy
źródło
1
Nie wygra, ale było fajnie - myślę tak samo, gdy publikuję swoje rozwiązania w języku C # :)
Cristian Lupascu
1
Możesz użyć $SECONDSzmiennej powłoki, aby uprościć obliczanie upływającego czasu.
manatwork
Możesz usunąć 2 kolejne znaki: 1) :w domyślnym rozszerzeniu parametru wartości; 2) $przed SECONDSobliczeniem arytmetycznym. W rzeczywistości jest inny dodatkowy znak, nowa linia na końcu pliku.
manatwork
4

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

Całkiem proste, jestem pewien, że należy wprowadzić ulepszenia. Pobiera nazwę pliku słownika jako argument wiersza polecenia.

EDYCJA : Kilka drobnych poprawek, głównie dotyczących zachowania nowych wierszy ze słownika. W rezultacie plik będzie wymagał końcowego znaku nowej linii, aby działać poprawnie.

Paul Prestidge
źródło
4

C, 305 309 347 znaków

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

Dzięki @ugoren za wskazówki dotyczące ulepszeń. Używanie „jedenastego słowa” do odrzucania przychodzących wpisów słownika było dużą wygraną w porównaniu z moim poprzednim podejściem strcpy-if-selected.

Oto źródło bez golfa:

#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;
}
chlebak
źródło
Pewne ulepszenia 1. K & Zgłoszenie r: main(n,v)char**v;{.... 2. stdinmoże być char *. fgets(buf,len,stdin)= gets(buf)(nie wspominając o przepełnieniu bufora). 3. Co jest nie tak rand()%i? RAND_MAXnie jest potrzebne. 4. Dlaczego long?
ugoren
1
Również: 1) t=time(0)-> time(&t). 2) n*60/(time(0)-t)ma nawiasów, że musi iść - *60mogą zostać przeniesione do n+=60*printf, a następnie n/=time(0)-t. 3) Zamień bna dodatkowy element w w, zamień na strcpywczytany bezpośrednio do w.
ugoren
Wymiana fgets()z gets()potrzeby dodatkowego kodu do czynienia z nowymi liniami w słowniku; to skończyło się na krótszym czasie. rand()%inie wystarcza; faktyczne obliczenia to (double)i*rand()/RAND_MAX. Przeniesienie *60do printf oznacza również zmianę na, -4aby -240ostatecznie zakończyć się stratą. Twoje pozostałe punkty są jednak ważne (uważam). Aha, longponieważ czas tradycyjnie jest długi. To, że gramy w golfa, nie oznacza, że ​​nie możemy być przenośni.
breadbox
Przegapiłem 4-> 240... Przenośność i golf nie idą w parze. Ale zdefiniowanie i,t;(domyślnie int) jest OK do MAX_INTkilku sekund (jeśli nie używasz time(&t)). Dzięki rand()wszystko, czego potrzebujesz, to 10/iszansa i rand()%i<10to robi.
ugoren
Twój losowy wybór jest nieco wadliwy (nie żeby absolutna sprawiedliwość była wymagana). 11. linia powinna mieć szansę na wybranie 10/11, ale robisz to rand()%10>10, co daje jej 100%. rand()%(i+1)>9jest lepszy (ale zamiast tego, jeśli %(i+1)tak i++>9?. Przenieś *stdinsię też jako pierwszy i oszczędzaj miejsce.
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!");}

Uruchomiona wersja tutaj: http://ideone.com/Nt6Id

Cristian Lupascu
źródło
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))

To jest w python 2.x, w 3.x mogę ogolić 4 dodatkowe znaki, używając funkcji drukowania.

Zawiera nowe linie

Joel Cornett
źródło
2
„Pytanie: Czy nowe linie się liczą?” Zwykle używamy „niezbędnych znaków”. W przypadku Pythona tak, nowe wiersze muszą zostać policzone, ponieważ ich usunięcie uniemożliwi działanie programu.
Joey Adams,
1
Myślę, że możesz się zmienić z=lambda x:na def z(x):.
Joey Adams,
@JeyeyAdams: Mógłbym, gdyby tylko musiał zwrócić, ale muszę wrócić len(x)i def z(x):returnjest jeszcze 5 postaci: /
Joel Cornett
Myślę, że możesz wygrać niektóre postacie, przesyłając dane wejściowe (dozwolone w pytaniu) i używając input()zamiastsys.argv[1].read()
ChristopheD
@JoelCornett: Ups, masz rację.
Joey Adams,
2

PHP 187 bajtów

Dla jasności dodano nowe linie:

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

Akceptuje nazwę pliku słownika jako argument wiersza poleceń. Plik słownika musi kończyć się nową linią.

primo
źródło
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!")
Książę John Wesley
źródło