# Viết trình chấm (aka stress code) but easier to understand ###### Author: zeena (i2225 PTNK) ###### Reviewer: DeMen100ns (HCMUS), Lucian (i2225 LHP) ###### Tài liệu tham khảo: [VNOI Wiki](https://wiki.vnoi.info/vi/algo/skill/viet-trinh-cham) :::success :bulb: Mình **khuyến khích** bạn nên đọc song song shitpost này và tài liệu tham khảo ở trên. ::: --- ## Why stress code? Đơn giản thôi, bởi vì tại sao không? Việc stress code có ưu điểm rất lớn, nhưng cái gì cũng có cái ưu và cái nhược. ### Ưu điểm Đây được xem như là 1 trình chấm không chính thức. Việc này giúp bạn phát hiện các trường hợp bạn sai nhanh chóng. Không chỉ vậy nó còn rất dễ cài đặt. Chính vì vậy, stress code là 1 trong những skill rất quan trọng mà bạn nên dùng các kỳ thi offline (như thi đội tuyển Tỉnh, VOI, ...) ### Nhược điểm Nhược điểm duy nhất của stress code là vì nó sinh test ngẫu nhiên, sẽ có khả năng bạn sẽ không thể xác định hết tất cả các trường hợp. ## What is that? Lấy code duyệt trâu bò làm chuẩn (không phải thuật chuẩn), vì trâu bò là **vua** của mọi loại thuật toán, vừa có khả năng cao cho ra kết quả chuẩn (với độ chính xác có thể lên tới **100%**), vừa dễ kiếm điểm, nhưng tốn nhiều thời gian, dễ dẫn đến TLE khi vượt quá giới hạn cho phép. Gọi đây là $X$, ta sẽ so sánh kết quả xuất ra của $X$ và bài làm của mình. ## How does it work? Stress code dựa vào các câu lệnh của Command Prompt (aka CMD) nếu bạn dùng hệ điều hành cửa sổ, còn của Linũ thì bạn có thể đọc tài liệu tham khảo mà mình đã liệt kê ở trên. Còn MacOS? Mình bó tay. ### Trình chạy Trước hết ta có câu lệnh như sau: ``` *tênchươngtrình*.exe ``` Đây là câu lệnh chạy file `.exe` của hệ thống. Thông thường, nếu file `.cpp` của bạn có tên là `main`, thì khi file được dịch thành công, `main.exe` sẽ xuất hiện trong thư mục chứa file của bạn. Khi đấy, câu lệnh trong CMD để chạy chương trình là `main.exe`. Để chạy file trong C++, ta có: ```cpp! system("*tênchươngtrình*.exe"); ``` ### Trình so Trong CMD, ta có câu lệnh so sánh 2 file như sau: ``` fc file1.x1 file2.x2 ``` Lệnh này sẽ trả về `0` nếu 2 file hoàn toàn giống nhau. Lấy `file.out` là output của bài làm của bạn và `file.ans` là kết quả của $X$. Khi đấy, câu lệnh của bạn sẽ trả về `0` nếu output của bạn trùng với output của $X$. Còn không thì bạn sai. Trong C++, lệnh này có thể viết như sau: ```cpp! system("fc *tênfile*.out *tênfile*.ans"); ``` ## How can I implement that? Trước khi viết trình chấm, bạn chuẩn bị sẵn **code trâu bò** của bạn ra. Format trình chấm khá đơn giản. Trong file trình chấm bao gồm: - Xác định số test cần chạy - Với mỗi test: - Xuất các số ngẫu nhiên theo format vào file `.inp` và lấy làm file input chung. - Chạy file bài làm của bạn và file $X$. - Lấy giá trị của lệnh so sánh 2 file kết quả. - Kiểm tra giá trị đó. Nếu nó khác `0` thì lập tức thoát khỏi trình chấm. Ví dụ: nếu input format là như thế này: ``` a b ``` Thì bạn sẽ xuất vào file `.inp` như sau: ```cpp! ofstream inp(("*tênfile*.inp")); inp << số_ngẫu_nhiên1 << ' ' << số_ngẫu_nhiên2; inp.close(); ``` Bạn có thể viết giống code mẫu ở dưới hoặc là giống với template của tài liệu tham khảo ở đầu trang vì code mẫu ở dưới hay code ở VNOI Wiki hầu như là y chang nhau, không khác gì nhau cả. Code mẫu: ```cpp! #include <bits/stdc++.h> using namespace std; mt19937 rd(chrono::steady_clock::now().time_since_epoch().count()); long long Rand(long long l, long long h) { assert(l <= h); return abs(l + rd() * 1LL * rd() % (h - l + 1)); } const int maxT = 100; int main() { srand(time(NULL)); for (int T = 1; T<=maxT; T++) { ofstream inp(("file.inp")); //lệnh input số ngẫu nhiên tại đây inp.close(); system(("sol.exe")); system(("sol_trau.exe")); if (system(("fc file.out file.ans")) != 0) { cout << "Test " << T << ": WRONG!\n"; return 0; } cout << "Test " << T << ": OK\n"; } } ``` ## When to use? Hầu như là bất cứ khi nào thuật trâu bò không phải là thuật chạy tốt nhất, và bạn đang code thuật tối ưu, bạn nên làm điều này. Và tất nhiên, sẽ có một số trường hợp tự sinh test bằng tay sẽ mang lại hiểu quả cao hơn.