Mở đầu
Sau hai phần trước em, chưa hài lòng về hệ thống hiện tại em tiếp tục đi tìm các hướng đi mới. Thật sự có các open source của mảng này làm rất ổn áp rồi, chủ yếu là mục đích học tập nên em vẫn muốn làm lại cái “bánh xe”.
Open source: RemoteCodeCompiler
An online code compiler supporting 11 programming languages (Java, Kotlin, Scala, C, C++, C#, Golang, Python, Ruby, Rust and Haskell) for competitive programming and coding interviews.
Đây là đoạn giới thiệu của nó trên github. Nôm na nó là 1 open source được viết bằng Java dùng để compiler code online.
Sau một hồi tìm kiếm em thấy thằng này có vẻ phù hợp tiêu chí không code giới hạn tài nguyên bằng C, và hoạt động cũng đơn giản.
Cách hoạt động
- Khi gửi file code lên nó sẽ khởi tạo 1 container để compiler (ở thời điểm em đọc mấy tháng trước nó không có cái này, không biết mục đích nó bổ sung thêm thằng này làm gì?)
- Sau khi compiler xong nó sẽ khởi tạo 1 container dùng để chạy file vừa được compiler và phản hồi lại kết quả.
Chi tiết cách họ compiler và giới hạn tài nguyên
Thay vì dùng C thì họ dùng bash script
để làm điều đó. Cụ thể khi ta upload file input
, output
và các thông số giới hạn thời gian
, bộ nhớ
họ sẽ tạo 1 file entrypoint.sh
với nội dung như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token shebang important">#!/usr/bin/env bash</span> <span class="token assign-left variable">rename</span><span class="token operator">=</span><span class="token variable">${compiler.rename}</span> <span class="token assign-left variable">compile</span><span class="token operator">=</span><span class="token variable">${compiler.compile}</span> <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token string">"<span class="token variable">$rename</span>"</span> <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span> <span class="token function">mv</span> <span class="token variable">${compiler.defaultName}</span> <span class="token variable">${compiler.fileName}</span> <span class="token keyword">fi</span> <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token string">"<span class="token variable">$compile</span>"</span> <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span> <span class="token variable">${compiler.compilationCommand}</span> <span class="token operator"><span class="token file-descriptor important">1</span>></span> /dev/null <span class="token assign-left variable">ret</span><span class="token operator">=</span><span class="token variable">$?</span> <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token variable">$ret</span> -ne <span class="token number">0</span> <span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">then</span> <span class="token builtin class-name">exit</span> <span class="token variable">${compiler.compilationErrorStatusCode}</span> <span class="token keyword">fi</span> <span class="token keyword">fi</span> <span class="token builtin class-name">ulimit</span> -s <span class="token variable">${compiler.memoryLimit}</span> <span class="token function">timeout</span> -s SIGTERM <span class="token variable">${compiler.timeLimit}</span> <span class="token variable">${compiler.executionCommand}</span> <span class="token builtin class-name">exit</span> <span class="token variable">$?</span> |
- Giải thích:
- Các ${} là template khi họ generate các chỗ này sẽ được truyền giá trị vào.
rename = true
thì sẽ đổi tên bằng commandmv
compile = true
thì sẽ chạy command compiler tương ứng của ngôn ngữ đó (tại vì một số ngôn ngữ không cần compiler)- Sử dụng command
ulimit
để giới hạn bộ nhớ, commandtimeout
để giới hạn thời gian - Dựa vào
exit code
để phân biệt các lỗi runtime, compiler, vượt quá thời gian hay bộ nhớ.
Vậy công việc còn lại là chạy file entrypoint.sh
này bằng các ngôn ngữ lập trình bắt exit code nếu không lỗi thì so sánh với đáp án đúng.
Triển khai ý tưởng
1. Viết code generate file entrypoint
Với template string của js thì việc tạo ra file entrypoint ez =))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <span class="token keyword">const</span> <span class="token function-variable function">generateEntryPointFile</span> <span class="token operator">=</span> <span class="token keyword">async</span><span class="token punctuation">(</span><span class="token parameter">compiler<span class="token punctuation">,</span> path</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> content <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">#!/usr/bin/env bash rename=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>rename<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> compile=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>compile<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> if [ "$rename" = true ]; then mv </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>defaultName<span class="token interpolation-punctuation punctuation">}</span></span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>fileName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> fi if [ "$compile" = true ]; then </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>compilationCommand<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> 1> /dev/null ret=$? if [ $ret -ne 0 ]; then exit </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>compilationErrorStatusCode<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> fi fi ulimit -s </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>memoryLimit<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> timeout -s SIGTERM </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>timeLimit<span class="token interpolation-punctuation punctuation">}</span></span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>compiler<span class="token punctuation">.</span>executionCommand<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> exit $?</span><span class="token template-punctuation string">`</span></span> <span class="token keyword">await</span> fs<span class="token punctuation">.</span><span class="token function">writeFile</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/entrypoint.sh</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> content<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
2. Định nghĩa các command compiler
ENUM_COMPILATION_CMD
: Các comand compiler
ENUM_EXCECUTION_CMD
: Các command để chạy code
ENUM_MESSAGE
: exit code tương ứng với ý nghĩa.
Ví dụ sau này muốn update thì chỉ việc bổ sung command vào
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">const</span> <span class="token constant">ENUM_COMPILATION_CMD</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"c"</span><span class="token operator">:</span> <span class="token string">"gcc main.c -o exec"</span><span class="token punctuation">,</span> <span class="token string">"cpp"</span><span class="token operator">:</span> <span class="token string">"g++ main.cpp -o exec"</span><span class="token punctuation">,</span> <span class="token string">"java"</span><span class="token operator">:</span> <span class="token string">"javac main.java"</span><span class="token punctuation">,</span> <span class="token string">"python"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token string">"js"</span><span class="token operator">:</span> <span class="token string">""</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token constant">ENUM_EXCECUTION_CMD</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"c"</span><span class="token operator">:</span> <span class="token string">"./exec"</span><span class="token punctuation">,</span> <span class="token string">"cpp"</span><span class="token operator">:</span> <span class="token string">"./exec"</span><span class="token punctuation">,</span> <span class="token string">"java"</span><span class="token operator">:</span> <span class="token string">"java Main"</span><span class="token punctuation">,</span> <span class="token string">"python"</span> <span class="token operator">:</span> <span class="token string">"python3 main.py"</span><span class="token punctuation">,</span> <span class="token string">"js"</span><span class="token operator">:</span> <span class="token string">"node main.js"</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token constant">ENUM_MESSAGE</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"0"</span><span class="token operator">:</span> <span class="token string">"Accepted"</span><span class="token punctuation">,</span> <span class="token string">"1"</span><span class="token operator">:</span> <span class="token string">"Wrong Answer"</span><span class="token punctuation">,</span> <span class="token string">"139"</span> <span class="token operator">:</span> <span class="token string">"Out Of Memory"</span><span class="token punctuation">,</span> <span class="token string">"124"</span><span class="token operator">:</span> <span class="token string">"Time Limit Exceeded"</span><span class="token punctuation">,</span> <span class="token string">"96"</span><span class="token operator">:</span> <span class="token string">"Compilation Error"</span> <span class="token punctuation">}</span> |
3. Tạo các object compiler truyền vào hàm generate entrypoint
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">const</span> <span class="token function-variable function">compiler</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">input<span class="token punctuation">,</span> memoryLimit<span class="token punctuation">,</span> timeLimit<span class="token punctuation">,</span> lang</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">let</span> compile <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token keyword">let</span> executionCommand <span class="token operator">=</span> <span class="token constant">ENUM_EXCECUTION_CMD</span><span class="token punctuation">[</span>lang<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token constant">ENUM_COMPILATION_CMD</span><span class="token punctuation">[</span>lang<span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">""</span><span class="token punctuation">)</span> compile <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token keyword">let</span> compiler <span class="token operator">=</span> <span class="token punctuation">{</span> rename<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> compile<span class="token punctuation">,</span> compilationCommand<span class="token operator">:</span> <span class="token constant">ENUM_COMPILATION_CMD</span><span class="token punctuation">[</span>lang<span class="token punctuation">]</span><span class="token punctuation">,</span> compilationErrorStatusCode<span class="token operator">:</span> <span class="token number">96</span><span class="token punctuation">,</span> executionCommand<span class="token punctuation">,</span> memoryLimit<span class="token punctuation">,</span> timeLimit<span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> compiler<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
4. Chạy container và lấy kết quả
--cpus=1
: giới hạn cpu của container
--rm
: Sau khi chạy xong thì cho bay màu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <span class="token keyword">const</span> <span class="token function-variable function">runContainer</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span> folder</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> cmdBuildImage <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">docker build -t </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>folder<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token keyword">const</span> cmdRunContainer <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">docker run --cpus=1 --rm </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> stdout<span class="token punctuation">,</span> stderr <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">exec</span><span class="token punctuation">(</span>cmdBuildImage<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>stdout<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"Successfully"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> ls <span class="token operator">=</span> <span class="token function">spawn</span><span class="token punctuation">(</span><span class="token string">"docker"</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">"run"</span><span class="token punctuation">,</span> <span class="token string">"--cpus=1"</span><span class="token punctuation">,</span> <span class="token string">"--rm"</span><span class="token punctuation">,</span> name<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">let</span> result <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span> ls<span class="token punctuation">.</span>stdout<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"data"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> result<span class="token punctuation">.</span>output <span class="token operator">=</span> data<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ls<span class="token punctuation">.</span>stderr<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"data"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> result<span class="token punctuation">.</span>stack <span class="token operator">=</span> data<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ls<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"close"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">code</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">child process close all stdio with code </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>code<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ls<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"exit"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">code</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> result<span class="token punctuation">.</span>code <span class="token operator">=</span> code<span class="token punctuation">;</span> <span class="token function">resolve</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> |
Một số vấn đề khi triển khai
1. Việc so sánh kết quả
Ta đọc ouput của container và dùng hàm đọc file để so sánh kết quả nó không good cho lắm, nên sau em lưu đáp án đúng vào redis giúp tốc độ đọc nhanh hơn.
1 2 3 4 5 6 7 | SET output:id { "01": "1 2 3" "02": "1 2 3 4 5", "03": "1" } |
Sau đó em quyết định so sánh luôn trong file entrypoint.sh
1 2 3 4 | <span class="token assign-left variable">raw</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token builtin class-name">ulimit</span> -s $<span class="token punctuation">{</span>compiler.memoryLimit<span class="token punctuation">}</span> <span class="token operator">&&</span> <span class="token function">timeout</span> -s SIGTERM $<span class="token punctuation">{</span>compiler.timeLimit<span class="token punctuation">}</span> $<span class="token punctuation">{</span>compiler.executionCommand<span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token string">"<span class="token variable">${inputFileName}</span>"</span><span class="token variable">)</span></span> <span class="token assign-left variable">ans</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">cat</span> <span class="token string">"out1.txt"</span><span class="token variable">)</span></span> <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token string">"<span class="token variable">$raw</span>"</span> <span class="token operator">==</span> <span class="token string">"<span class="token variable">$ans</span>"</span> <span class="token punctuation">]</span> |
2. Việc chạy nhiều test đồng thời
Thay vì phải khởi mỗi container cho 1 test thì em chuyển hết file input
và output
vào 1 container rồi dùng for
của bash để chạy
1 2 3 4 5 6 | <span class="token assign-left variable">count</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">find</span> <span class="token builtin class-name">.</span> -name <span class="token string">"in*.txt"</span> <span class="token operator">|</span><span class="token function">wc</span> -l<span class="token variable">)</span></span><span class="token variable"><span class="token variable">`</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token for-or-select variable">i</span> <span class="token keyword">in</span> <span class="token variable">`</span></span><span class="token function">seq</span> <span class="token number">1</span> <span class="token variable">$count</span>` <span class="token keyword">do</span> run_code <span class="token variable">$i</span> <span class="token variable">$1</span> <span class="token keyword">done</span> |
sau đó viết hàm run_code
đối số truyền vào số thứ tự của file input
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token function-name function">run_code</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token assign-left variable">start</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">date</span> +%s.%N<span class="token variable">)</span></span> <span class="token assign-left variable">raw</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token builtin class-name">ulimit</span> -s $<span class="token punctuation">{</span>compiler.memoryLimit<span class="token punctuation">}</span> <span class="token operator">&&</span> <span class="token function">timeout</span> -s SIGTERM $<span class="token punctuation">{</span>compiler.timeLimit<span class="token punctuation">}</span> $<span class="token punctuation">{</span>compiler.executionCommand<span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token string">"<span class="token variable">${inputFileName}</span>"</span><span class="token variable">)</span></span> <span class="token assign-left variable">code</span><span class="token operator">=</span><span class="token variable">$?</span> <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token variable">$code</span> -eq <span class="token number">0</span> <span class="token punctuation">]</span> <span class="token keyword">then</span> <span class="token assign-left variable">ans</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">cat</span> <span class="token string">"out<span class="token variable">${1}</span>.txt"</span><span class="token variable">)</span></span> <span class="token punctuation">..</span>. <span class="token keyword">if</span> <span class="token punctuation">[</span> <span class="token string">"<span class="token variable">$raw</span>"</span> <span class="token operator">==</span> <span class="token string">"<span class="token variable">$ans</span>"</span> <span class="token punctuation">]</span> <span class="token keyword">then</span> <span class="token punctuation">..</span>. <span class="token builtin class-name">return</span> <span class="token number">1</span> <span class="token keyword">else</span> <span class="token punctuation">..</span>. <span class="token builtin class-name">return</span> <span class="token number">1</span> <span class="token keyword">fi</span> <span class="token keyword">else</span> <span class="token punctuation">..</span>. <span class="token keyword">fi</span> <span class="token builtin class-name">printf</span> <span class="token string">'%s|'</span> <span class="token string">"<span class="token variable">$JSON</span>"</span> <span class="token punctuation">}</span> |
Vấn đề: Nếu chạy vòng lặp thì nó sẽ bị chạy “tuần tự” (mỗi test để giới hạn 2s thì 10 cái test nếu xui mất 20s) vậy ta cần chạy nó “đồng thời”
Google thì solution là thêm &
vào để nó chạy “đồng thời”
1 2 3 4 5 6 | <span class="token assign-left variable">count</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span><span class="token function">find</span> <span class="token builtin class-name">.</span> -name <span class="token string">"in*.txt"</span> <span class="token operator">|</span><span class="token function">wc</span> -l<span class="token variable">)</span></span><span class="token variable"><span class="token variable">`</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token for-or-select variable">i</span> <span class="token keyword">in</span> <span class="token variable">`</span></span><span class="token function">seq</span> <span class="token number">1</span> <span class="token variable">$count</span>` <span class="token keyword">do</span> run_code <span class="token variable">$i</span> <span class="token variable">$1</span> <span class="token operator">&</span> <span class="token keyword">done</span> |
3. Nhập từ bàn phím với javascript
Việc nhập vào từ bàn phím với ngôn ngữ js thì ta có thể sử dụng readline
nhưng em để ý một số thằng ví dụ như leetcode nó không cần người dùng có thằng này mà nó vẫn hiểu ảo ma vch =))
1 2 3 4 5 | <span class="token comment">//Leetcode</span> <span class="token keyword">function</span> <span class="token function">solution</span><span class="token punctuation">(</span><span class="token parameter">a<span class="token punctuation">,</span> b</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// code here</span> <span class="token punctuation">}</span> |
Vấn đề: Như trên ta chỉ cần viết code vào trong function, việc truyền biến vào thì leetcode sẽ lo. Làm sao để có thể truyền động các đối số như họ ?
Ban đầu em nghĩ đến việc for các đối số rồi generate các hàm readline, nhưng biết sao được các đối số là kiểu dữ liệu nào để parse cho đúng (vì input ghi trong file text thì nó sẽ auto kiểu string). Rồi còn kiểu mảng, kiểu object truyền kiểu gì ?
Trường hợp này file text không chơi được với js vậy mình dùng json. Vậy nó sẽ có dạng
1 2 3 4 | <span class="token punctuation">{</span> <span class="token property">"in"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> |
Khi dùng json thì ta có thể dùng bất kì kiểu dữ liệu nào ta thích number, string, array, object.
Vậy truyền nó vào hàm solution kiểu gì ? Đáp dòng này vào cuối file code js của người dùng là được
1 2 3 4 5 6 7 8 | process<span class="token punctuation">.</span>stdin<span class="token punctuation">.</span><span class="token function">resume</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> process<span class="token punctuation">.</span>stdin<span class="token punctuation">.</span><span class="token function">setEncoding</span><span class="token punctuation">(</span><span class="token string">"utf8"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> process<span class="token punctuation">.</span>stdin<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">"data"</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">input</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> data <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>input<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">solution</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> data<span class="token punctuation">.</span>in<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Kết
- Hệ thống có vẻ hoạt động đúng yêu cầu đề ra.
- Nó chưa hoàn hảo như em kỳ vọng vì em muốn giới hạn thêm một số tài nguyên nữa nhưng không thể. Chắc có lẽ đấy là lý do người ta dùng C để giới hạn tài nguyên.
- Hành trình theo đổi cái hệ thống này em cũng học được nhiều cái hay