1. Trang chủ
  2. » Công Nghệ Thông Tin

Tự code, tự chấm, tự sướng bí kíp thi offline

6 137 0

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 6
Dung lượng 24,02 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Đây là một thứ sẽ rất giúp ích cho các bạn HS chuyên tin đặc biệt là các bạn chuẩn bị thI HSG quốc gia các kĩ năng trong đây sẽ giúp các bạn rất là nhiều và nó là 1 điều ko thể thiếu với những ai sắp có kì thi HSG quóc gia sắp tới hay các cuộc thi tin như APIO,COCI,.. và cũng như trong các cuộc thi trên mạng của Online Judge như Codeforces,Atcoder,..

Trang 1

T  code, t  ch m, t  s ự ự ấ ự ướ ng ­ 

Bí kíp thi offline

Tác giả: Vũ chipchip Phúc Hoàng

B n c m th y lo s  trong nh ng kì thi ch m offline? B n bình thạ ả ấ ợ ữ ấ ạ ường làm bài r t t t ấ ố

nh ng khi ch m offline l i b  đi m kém vì sai nh ng l i v  v n? B n code sai m t bài r tư ấ ạ ị ể ữ ỗ ớ ẩ ạ ộ ấ khó và debug mãi không được vì không có test sai? T t c  nh ng v n đ  đó s  đấ ả ữ ấ ề ẽ ược 

gi i quy t đ n gi n v i m t chả ế ơ ả ớ ộ ương trình ch m bài t  đ ng, giúp b n t  ki m tra bài ấ ự ộ ạ ự ể mình và phát hi n test sai. Bài vi t này s  gi i thi u v i b n nh ng bệ ế ẽ ớ ệ ớ ạ ữ ước c  b n nh t ơ ả ấ

đ  vi t trình ch m ­ m t kĩ thu t mà b n nên thành th o trể ế ấ ộ ậ ạ ạ ước khi thi HSG Qu c gia.ố

Table of Contents

 Trình ch m là gì? ấ

 T i sao nên vi t trình ch m? ạ ế ấ

 Khi nào nên vi t trình ch m? ế ấ

 Thành ph n c a m t b  trình ch m ầ ủ ộ ộ ấ

o L i gi i 1:ờ ả

o L i gi i 2:ờ ả

 Ví d : Bài VMELLIP ụ

o L i gi i 1:ờ ả

o L i gi i 2:ờ ả

o Trình sinh test + Trình so test:

 Làm sao đ  vi t trình ch m m t cách hi u qu ? ể ế ấ ộ ệ ả

o Template dành cho Pascal:

o Template dùng Shell script

 Luy n t p vi t trình ch m ệ ậ ế ấ

Trình ch m là gì? ấ

Trình ch m là m t b  chấ ộ ộ ương trình giúp b n t  đ ng sinh ra các test input ng u nhiên ạ ự ộ ẫ

và t  đ ng ch y hai chự ộ ạ ương trình l i gi i khác nhau v i các input đó đ  so sánh output. ờ ả ớ ể

V  c  b n, trình ch m g m 4 chề ơ ả ấ ồ ương trình là: l i gi i 1, l i gi i 2, trình sinh test, và trìnhờ ả ờ ả

so test. Thường thì l i gi i 1 là cách chu n b n s  s  d ng, còn l i gi i 2 là m t cách cóờ ả ẩ ạ ẽ ử ụ ờ ả ộ

hi u qu  kém h n nh ng v n chính xác.ệ ả ơ ư ẫ

T i sao nên vi t trình ch m? ạ ế ấ

Vi t trình ch m là m t trong nh ng cách ki m tra bài c a mình đáng tin c y nh t. V i ế ấ ộ ữ ể ủ ậ ấ ớ

nh ng kì thi ch m offline, ví d  nh  VOI, vi c sai sót nh  r t khó tránh kh i khi ta không ữ ấ ụ ư ệ ỏ ấ ỏ

Trang 2

th  bi t k t qu  trong khi thi. V y thì, n u nh  bài c a b n không để ế ế ả ậ ế ư ủ ạ ược ch m v i b  testấ ớ ộ

c a ban t  ch c, b n hãy t  ch m nó v i b  test ng u nhiên mà mình sinh. N u bài c a ủ ổ ứ ạ ự ấ ớ ộ ẫ ế ủ

b n đúng v i các test ng u nhiên, b n có th  t m yên tâm là bài s  đạ ớ ẫ ạ ể ạ ẽ ược đi m cao và ể không b  nh ng sai sót "chí m ng" d n đ n bài b  0 đi m.ị ữ ạ ẫ ế ị ể

Trình ch m yêu c u m t trình "chu n" và m t trình "trâu", và so sánh hai chấ ầ ộ ẩ ộ ương trình  này v i nhau. N u trình ch m c a b n phát hi n đớ ế ấ ủ ạ ệ ược m t test mà k t qu  hai chộ ế ả ương  trình không kh p nhau, trình chu n ho c trình trâu c a b n s  sai, và b n hãy s  d ng ớ ẩ ặ ủ ạ ẽ ạ ử ụ test đó đ  debug. Còn n u t t c  các test đ u đúng, b n có th  t m yên tâm, vì m c dù ể ế ấ ả ề ạ ể ạ ặ

có th  c  hai l i gi i cùng sai, nh ng cùng sai gi ng h t nhau thì r t khó.ể ả ờ ả ư ố ệ ấ

Đ i v i nh ng kì thi ch m online, ho c đ n gi n là b n làm bài online trên m ng, trình ố ớ ữ ấ ặ ơ ả ạ ạ

ch m cũng r t h u ích trong vi c tìm test sai. Ch ng h n khi b n code m t bài c u trúc ấ ấ ữ ệ ẳ ạ ạ ộ ấ

d  li u khó, n p bài th y b  0 đi m, thay vì vi c ng i debug b ng m t hãy th  code m t ữ ệ ộ ấ ị ể ệ ồ ằ ắ ử ộ

b  trình ch m đ  giúp tìm test sai. V i test sai tìm độ ấ ể ớ ược b n s  d  dàng debug h n r t ạ ẽ ễ ơ ấ nhi u.ề

Nhi u ngề ười ng i vi t trình ch m vì cho r ng làm v y m t th i gian. Tuy nhiên, khi đã ạ ế ấ ằ ậ ấ ờ thành th o thì vi t m t b  trình ch m cho m t bài ch  m t kho ng 10 phút, n u nh  bài ạ ế ộ ộ ấ ộ ỉ ấ ả ế ư

đó có th  làm trâu và sinh test ng u nhiên m t cách d  dàng. L i th  v  m t tâm lí khi ể ẫ ộ ễ ợ ế ề ặ

đã bi t ch c bài làm c a mình đúng s  giúp b n làm bài hi u qu  h n, th c t  s  ti t ế ắ ủ ẽ ạ ệ ả ơ ự ế ẽ ế

ki m đệ ược th i gian so v i khi không ki m tra bài. Tờ ớ ể ương t , vi t trình ch m đ  debug ự ế ấ ể

nh ng bài code khó đôi khi hi u qu  h n nhi u so v i vi c debug b ng m t, ti t ki m ữ ệ ả ơ ề ớ ệ ằ ắ ế ệ

đượ ấc r t nhi u th i gian.ề ờ

Khi nào nên vi t trình ch m? ế ấ

L i khuyên c a tác gi  là: Hãy vi t trình ch m b t c  lúc nào mà bài có th  làm trâu và ờ ủ ả ế ấ ấ ứ ể

có th  t m b  qua, tuy nhiên n u có th i gian v n nên vi t trình ch m sau đ y đ  đ m ể ạ ỏ ế ờ ẫ ế ấ ấ ể ả

b o ch c ch n.ả ắ ắ

Thành ph n c a m t b  trình  ầ ủ ộ ộ

ch m ấ

L u ý: ư  Bài vi t này hế ướng d n cho Pascal/C++ trên h  đi u hành Windows. V i các ẫ ệ ề ớ ngôn ng  khác ho c ch y trên h  đi u hành khác, m t s  l nh s  thay đ i, tuy nhiên ý ữ ặ ạ ệ ề ộ ố ệ ẽ ổ

tưởng v n tẫ ương t ự

M t b  trình ch m g m có 4 thành ph n: L i gi i 1, l i gi i 2, trình sinh test, trình so ộ ộ ấ ồ ầ ờ ả ờ ả test

L i gi i 1: ờ ả

Thường là code chu n c a b n. Dù vi t trình ch m hay không thì ph n này b t bu c ẩ ủ ạ ế ấ ầ ắ ộ

ph i có nên cũng không c n ph i nói nhi u. Trong bài vi t này, ta s  gi  s  input c a ả ầ ả ề ế ẽ ả ử ủ trình l i gi i 1 làờ ả  *.inp, output là *.out

Trang 3

L i gi i 2: ờ ả

Thường là code trâu, ho c là m t cách gi i khác, mi n là ra đúng đáp s  Hãy ch n ặ ộ ả ễ ố ọ cách d  code nh t, d  đúng nh t có th , vì th i gian ch y th c ra không quan tr ng l m ễ ấ ễ ấ ể ờ ạ ự ọ ắ khi b n ch  c n sinh test nh  đ  ki m tra. Trong bài vi t này, ta s  gi  s  input c a trình ạ ỉ ầ ỏ ể ể ế ẽ ả ử ủ

l i gi i 2 làờ ả  *.inp, output là *.ans

Trình sinh test:

Chương trình này có nhi m v  sinh input ng u nhiên vào fileệ ụ ẫ  *.inp. Đ  cho hàm ng u ể ẫ nhiên được thay đ i khi chổ ương trình kh i đ ng, s  d ng l nhở ộ ử ụ ệ  randomize trong Pascal 

và srand(time(NULL)) trong C++

L u ý: ư  L nhệ  srand(time(NULL)) trong C++ tính random theo giây, t c là sau 1 giây nó m iứ ớ thay đ i random seed. Vì v y nhi u kh  năng các test random sinh ra liên t c s  b  ổ ậ ề ả ụ ẽ ị

gi ng nhau. Đ  kh c ph c đi u này, ta có th  l ng trình sinh test vào trình so test ch  ố ể ắ ụ ề ể ồ ứ không tách ra cho ch y riêng n a. V i Pascal thì không ph i lo v  đi u này, ạ ữ ớ ả ề ề

vì randomize thay đ i random seed theo mili giây.ổ

Trình so test:

Chương trình này có nhi m v  duy t N l n, v i N là s  test c n so, m i l n thì ch y trìnhệ ụ ệ ầ ớ ố ầ ỗ ầ ạ sinh test trước, xong đ n l n lế ầ ượ ờt l i gi i 1 và l i gi i 2. Sau khi ch y xong, ta có đả ờ ả ạ ược  file *.out và *.ans tương  ng là k t qu  c a hai chứ ế ả ủ ương trình l i gi i, và vi c còn l i là soờ ả ệ ạ sánh 2 file này v i nhau. N u k t qu  trùng nhau (ho c th a mãn đi u ki n đ  bài v i ớ ế ế ả ặ ỏ ề ệ ề ớ

nh ng bài có nhi u đáp s ), ta coi nh  test đó đúng và chuy n đ n test sau. N u khác ữ ề ố ư ể ế ế nhau, ta in ra sai và d ng chừ ương trình l i luôn, và ta có 3 fileạ  *.inp, *.out, *.ans là d  ữ

li u c a test sai.ệ ủ

Đ  ch y file, ta s  d ngể ạ ử ụ  exec('*.exe', '') trong Pascal và system("*.exe") trong C++

Ví d : Bài ụ   VMELLIP

Đây là m t bài c u trúc d  li u r t khó, thu c đ  thi VNOI Marathon 2015. Bài vi t xin ộ ấ ữ ệ ấ ộ ề ế

đượ ấc l y code c a tanphatls987 đủ ược 90 đi m làm ví d ể ụ

L i gi i 1: ờ ả

Link code

Đây là code c a tanphatls987, đủ ược thêm 2 dòng freopen vào đ  m  file. Code g c ể ở ố

L i gi i 2: ờ ả

Link code

Đây là code trâu v i đ  ph c t p O(N * M), làm y nh  nh ng gì đ  bài b o.ớ ộ ứ ạ ư ữ ề ả

Trình sinh test + Trình so test:

Link code

Vì đây là code C++ nên tác gi  k t h p trình sinh test v i trình so test đ  cho hàm ả ế ợ ớ ể

100 l n  ng v i 100 test, m i l n duy t ta sinh ng u nhiên ra file inputầ ứ ớ ỗ ầ ệ ẫ  vmellip.inp. Sau 

Trang 4

đó, ta l n lầ ượt ch y hai chạ ương trình   ở

trên: system("vmellip.exe") và system("vmellip_trau.exe") (l i gi i 2 đ t tên làờ ả ặ  vmellip_trau).  Sau đó ta s  d ng l nhử ụ ệ  system("fc vmellip.out vmellip.ans"), có nhi m v  so hai file ệ ụ

text vmellip.out và vmellip.ans v i nhau. N u hai file hoàn toàn kh p nhau, l nhớ ế ớ ệ  system sẽ

tr  v  exit code là 0, còn không s  tr  v  exit code là 1.ả ề ẽ ả ề

Ch y th  chạ ử ương trình này, ta có th  sinh để ược m t test sai nh  sau:ộ ư

1 5

6 6

3 1 1 8

1 1 1 1

6 1 1

1 1 1 9

2 1 1 8

9 8

Trong đó, l i gi i 1 ra output là:ờ ả

1

L i gi i 2 ra output là:ờ ả

0

Gi i h n test (dòng 3) đớ ạ ược đ t nh , m c đích là đ  sinh ra test sai nh  d  debug h n. ặ ỏ ụ ể ỏ ễ ơ Sau khi code đã đúng, có th  tăng gi i h n lên đ  ki m tra m nh h n.ể ớ ạ ể ể ạ ơ

Làm sao đ  vi t trình ch m m t  ể ế ấ ộ cách hi u qu ? ệ ả

Qua ví d  trên, b n có th  c m th y khá ng i khi code trình so test khá dài, code có th  ụ ạ ể ả ấ ạ ể

m t th i gian. Tuy nhiên, ta hoàn toàn có th  vi t code so test thành m t template đ  ấ ờ ể ế ộ ể

ng d ng cho t t c  các bài! V i m t template so test có s n, vi c còn l i c a ta ch  là 

code ph n sinh test và trình trâu, n u nh  đã làm quen v i trình ch m thì ch  m t ầ ế ư ớ ấ ỉ ấ

kho ng 10 phút đ  vi t.ả ể ế

Tác gi  xin đả ược chia s  v i các b n các template trình ch m do chính mình s  d ng.ẻ ớ ạ ấ ử ụ

Template dành cho C++:

#include <bits/stdc++.h>

using namespace std;

// Tên chương trình

const string NAME = "template";

Trang 5

// Số test kiểm tra

const int NTEST = 100 ;

// Viết lại hàm random để sử dụng cho thuận tiện Hàm random này sinh ngẫu nhiên số trong phạm

vi long long, số sinh ra >= l và <= h.

long long Rand(long long l, long long h)

{

return l + (( long long )rand() * (RAND_MAX + 1) * (RAND_MAX + 1) * (RAND_MAX + 1) +

(long long )rand() * (RAND_MAX + 1) * (RAND_MAX + 1) +

(long long )rand() * (RAND_MAX + 1) +

rand()) % (h - l + 1 );

}

int main()

{

srand(time( NULL ));

for( int iTest = 1; iTest <= NTEST; iTest++)

{

ofstream inp((NAME + ".inp").c_str());

// Code phần sinh test ở đây

inp.close();

// Nếu dùng Linux thì "./" + Tên chương trình

system((NAME + ".exe").c_str());

system((NAME + "_trau.exe").c_str());

// Nếu dùng linux thì thay fc bằng dif

if(system(("fc " + NAME + ".out " + NAME + ".ans").c_str()) != 0 )

{

cout << "Test " << iTest << ": WRONG!\n";

return 0 ;

}

cout << "Test " << iTest << ": CORRECT!\n";

}

return 0 ;

}

Template dành cho Pascal:

{$mode objfpc}

// Thư viện dos chứa lệnh exec

uses dos;

const

// Tên chương trình

NAM = 'template';

// Số test kiểm tra

NTEST = 100 ;

var

iTest: integer;

Trang 6

for iTest := 1 to NTEST do

begin

// Pascal không gặp vấn đề với randomize, vì vậy ta có thể tách trình sinh test riêng ra.

Exec(NAM + '_sinhtest.exe', '');

Exec(NAM + '.exe', '');

Exec(NAM + '_trau.exe', '');

Exec('fc', NAM + '.out ' + NAM + '.ans');

if DosExitCode <> 0 then

begin

writeln('Test ', iTest, ': WRONG!');

exit;

end;

writeln('Test ', iTest, ': CORRECT!');

end;

end.

Template dùng Shell script

Gi  s  b n có 2 code khác nhau, đã d ch ra 2 file executable làả ử ạ ị  prog1 và prog2. B n vi t ạ ế

v i C++ b n dùngớ ạ  srand(atoi(argv[1]))):

# Sinh 100 test

for((i=1;i<=100;i++)); do

# Sinh input với seed $i và lưu vào in_tmp

/gen $i > in_tmp

# So sánh output của 2 code, nếu output khác nhau thì dừng lại.

# Khi đó ta có file in_tmp chính là input mà 2 code chạy ra kết quả khác nhau.

diff <(./prog1 < in_tmp) <(./prog2 < in_tmp) || break

done

Luy n t p vi t trình ch m ệ ậ ế ấ

Đ  vi t trình ch m thành th o, hãy th  vi t trình ch m v i t t c  các bài mà b n luy n ể ế ấ ạ ử ế ấ ớ ấ ả ạ ệ

t p, cho đ n khi không còn ng i vi t trình ch m n a thì lúc đó b n s  thành công. Hãy ậ ế ạ ế ấ ữ ạ ẽ

đ t ra m c tiêu là m t sub AC v i t t c  các bài mình làm v i s  h  tr  c a trình ch m. ặ ụ ộ ớ ấ ả ớ ự ỗ ợ ủ ấ

M t khi đã thành th o tuy t kĩ này, b n s  d  dàng chinh ph c nh ng kì thi ch m offline ộ ạ ệ ạ ẽ ễ ụ ữ ấ

và không bao gi  ph i lo l ng làm sai n a.ờ ả ắ ữ

Ngày đăng: 05/02/2020, 21:34

TỪ KHÓA LIÊN QUAN

w