Xây dựng bài kiểm tra tốc độ gõ / đo CPM


11

Những quy định

Đã đến lúc xây dựng một bài kiểm tra tốc độ đánh máy bằng ngôn ngữ bạn chọn!

1 . Bạn cung cấp một tệp với một từ điển lựa chọn (mỗi 'từ' trong đó phải được phân cách bằng dòng mới). Đưa nó qua stdinhoặc cung cấp tên của nó như là một đối số dòng lệnh.

một
có thể
trong khoảng
ở trên
vắng mặt
...

2 . Chọn 10 từ ngẫu nhiên từ tệp (không được phép trùng lặp) và in chúng ra theo cách sau:

-> trực tiếp
-> mặt đất
-> tiếp theo
-> năm
...

3 . Bắt đầu đo thời gian từ bây giờ!

4 . Hãy để người dùng gõ tất cả mười từ càng nhanh càng tốt (kết thúc bằng việc trả lại xe ngựa). In OKkhi bạn có một trận đấu, in WRONGkhi chúng tôi có lỗi đánh máy (hoặc từ đã được gõ thành công trong lần chạy này).

5 . Dừng mấy cái đồng hồ lại! Bây giờ in điểm chuẩn CPM (Nhân vật mỗi phút), được tính như sau : (sum of the characters of the chosen words / time spent typing (seconds)) * 60. Làm tròn đến số nguyên gần nhất và sao chép đầu ra (mẫu) sau:

-> Bạn đã ghi được 344 CPM!

Chạy mẫu

-> giải quyết
-> bên
-> mở
-> bộ trưởng
-> rủi ro
-> màu
-> tàu
-> giống nhau
-> kích thước
-> kiếm
giải quyết
đồng ý
bên
đồng ý
mở
đồng ý
# ...................... một số dòng bị cắt ......................
từ
SAI LẦM
thanh kiếm
đồng ý
-> Bạn đã ghi được CPM CPM!

Người chiến thắng

Đây là mã colf, mục nhập ngắn nhất (tính theo số ký tự mã nguồn) thắng, hãy vui vẻ!


4
Tôi nghĩ rằng người chiến thắng nên được ghi điểm một phần bởi người có CPM cao nhất;)
mellamokb

Làm thế nào chính xác để chúng ta cần phải đo thời gian? Độ phân giải một giây có ổn không?
Ilmari Karonen

@Ilmari Karonen: một giải pháp một giây sẽ tốt cho cuộc thi cụ thể này.
BarsheD

Câu trả lời:


5

K, 146

Giả sử một tệp từ điển được gọi là 'd' trong thư mục làm việc hiện tại.

{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!";}

Rất đẹp và ngắn, mục đầu tiên trong Ktôi đã nhìn thấy (ở đây trên codegolf.se) ...
ChristopheD

Cảm ơn, tất cả các câu trả lời của tôi ở đây là bằng Q hoặc (ngày càng) trong K.
tmartin

Tôi không hiểu tại sao điều này chỉ có một upvote (của tôi)!
BarsheD

11

Bash - 217 212 199 196 ký tự

Không chiến thắng nhưng thật vui

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!

Dưới 200 ký tự bây giờ!

Lấy tệp danh sách từ làm đối số Bây giờ lấy danh sách từ trên đầu vào tiêu chuẩn. Dán nó vào thiết bị đầu cuối và nhấn ^ D

Đề xuất thực hiện từ manatwork


1
Sẽ không chiến thắng nhưng thật vui - Tôi cũng nghĩ như vậy khi tôi đăng các giải pháp C # của mình :)
Cristian Lupascu

1
Bạn có thể sử dụng $SECONDSbiến shell để đơn giản hóa việc tính thời gian đã trôi qua.
manatwork

Bạn có thể xóa thêm 2 ký tự: 1) :trong phần mở rộng tham số giá trị mặc định; 2) $phía trước SECONDStrong đánh giá số học. Trên thực tế có một nhân vật phụ khác, dòng mới tại và của tập tin.
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)

Khá cơ bản, tôi chắc chắn có những cải tiến sẽ được thực hiện. Lấy tên tệp của từ điển làm đối số dòng lệnh.

EDIT : Một vài điều chỉnh nhỏ, chủ yếu xoay quanh việc giữ lại các dòng mới từ từ điển. Kết quả là tập tin sẽ cần một dòng mới để hoạt động chính xác.


4

C, 305 309 347 ký tự

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

Cảm ơn @ugoren cho các gợi ý cải tiến. Sử dụng "từ thứ 11" để loại bỏ các mục từ điển đến là một chiến thắng lớn so với cách tiếp cận strcpy-if-select trước đây của tôi.

Đây là nguồn không rõ ràng:

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

Một số cải tiến: 1. Khai báo K & R : main(n,v)char**v;{.... 2. stdincó thể được char *. fgets(buf,len,stdin)= gets(buf)(không bao giờ để ý đến bộ đệm tràn ngập). 3. Điều gì sai với rand()%i? RAND_MAXkhông cần thiết 4. Tại sao long?
ugoren

1
Ngoài ra: 1) t=time(0)-> time(&t). 2) n*60/(time(0)-t)có dấu ngoặc đơn phải đi - sau đó *60có thể được chuyển đến . 3) Thay thế bằng một yếu tố phụ , thay thế bằng đọc trực tiếp vào . n+=60*printfn/=time(0)-tbwstrcpyw
ugoren

Thay thế fgets()bằng gets()nhu cầu thêm mã để đối phó với các dòng mới trong từ điển; vết thương này ngắn hơn rand()%ikhông đủ tính toán thực tế là (double)i*rand()/RAND_MAX. Di chuyển *60đến printf cũng có nghĩa là thay đổi thành -4để -240cuối cùng nó mất đi một mất mát. Điểm khác của bạn là những điểm hợp lệ, mặc dù (tôi tin). Oh, và longlà bởi vì time_t theo truyền thống là dài. Chỉ vì chúng tôi chơi golf không có nghĩa là chúng tôi không thể di động.
hộp bánh mì

Tôi đã bỏ lỡ 4-> 240... Tính di động và golf không kết hợp tốt với nhau. Nhưng việc xác định i,t;(ngầm định int) có thể lên đến MAX_INTvài giây (nếu bạn không sử dụng time(&t)). Với rand(), tất cả những gì bạn cần là một 10/icơ hội, và rand()%i<10thực hiện nó.
ugoren

Lựa chọn ngẫu nhiên của bạn có phần thiếu sót (không phải là sự công bằng tuyệt đối được yêu cầu). Dòng thứ 11 sẽ có cơ hội 10/11 để được chọn, nhưng bạn làm được rand()%10>10, nó mang lại 100%. rand()%(i+1)>9là tốt hơn (nhưng thay vào đó nếu %(i+1)làm i++>9?. Cũng di chuyển *stdinlên đầu tiên và tiết kiệm một không gian.
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!");}

Phiên bản đang chạy tại đây: http://ideone.com/Nt6Id


2

Con trăn ( 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))

Đây là trong python 2.x, trong 3.x tôi có thể cạo thêm 4 ký tự bằng cách sử dụng chức năng in.

Bao gồm các dòng mới


2
"Câu hỏi: Làm mới dòng mới?" Chúng tôi thường đi theo "các nhân vật cần thiết". Trong trường hợp của Python, vâng, các dòng mới cần được tính, vì việc loại bỏ chúng sẽ khiến chương trình không hoạt động.
Joey Adams

1
Tôi nghĩ bạn có thể thay đổi z=lambda x:để def z(x):.
Joey Adams

@JoeyAdams: Tôi có thể nếu không cần phải trả lại, nhưng tôi cần quay lại len(x)def z(x):returncó thêm 5 người từ thiện: /
Joel Cornett

Tôi nghĩ rằng bạn có thể giành được một số ký tự bằng cách nhập vào đầu vào (được cho phép trong câu hỏi) và sử dụng input()thay vìsys.argv[1].read()
BarsheD

@JoelCornett: Rất tiếc, bạn đã đúng.
Joey Adams

2

PHP 187 byte

Dòng mới đã được thêm vào cho rõ ràng:

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

Chấp nhận tên tệp từ điển làm đối số dòng lệnh. Các tập tin từ điển phải kết thúc với một dòng mới.


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!")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.