프로그래밍/NodeJS

[NodeJS] 프롬프트 기반 입출력 처리

Beginner:) 2024. 9. 23.
320x100

백준, 프로그래머스와 같은 알고리즘 문제 사이트를 만들 때, c 또는 cpp 등의 코드(text)를 넘겨주면 .c 또는 .cpp 파일로 저장한 뒤 컴파일하고 실행하여 standard I/O 까지 주는 방법이다.

 

알고리즘에는 테스트케이스가 여러개이기 때문에 input도 여러 개로 한다.

 

만약 python code라면 compile과정을 생략한다.

 


 

파일은 TypeScript로 작성하였다.

 

1. 코드

import { exec, spawn } from 'child_process';

function commandC( path: string, code: string, inputs: string[], outputs:string[], limit_time: number ):  Promise< string > {
    return new Promise((resolve, reject) => {
        let compileCommand = `gcc ${path}.c -o ${path}`;
        let runCommand = `${path}`;

        exec(compileCommand, (compileError) => {
            if (compileError) {
                console.log(compileError.message);
                return reject("build error");
            }

            var complete = 0;
            for ( let i = 0; i < inputs.length; i++ ) {
                const child = spawn(runCommand, { stdio: ['pipe', 'pipe', 'pipe'] }); // stdin, stdout, stderr 설정 

                let output: string = "";

                child.stdin.write(inputs[i]);
                child.stdin.end();

                child.stdout.on('data', (data) => { output = data.toString(); });
                child.stderr.on('data', (data) => { reject(`Error: ${data.toString()}`); });

                child.on('close', (code) => {
                    clearTimeout(timeoutId);
                    if (code === 0) {
                        if ( outputs[i] == output ) { complete++; }
                        else { reject(`fail`); }

                        if ( complete === inputs.length ) {
                            resolve("pass");
                        }
                    } 
                    else { reject(`Child process exited with code ${code}`); }
                });

                const timeoutId = setTimeout(() => {
                    child.kill();
                    reject(`Process timed out after ${limit_time}s`);
                    
                }, limit_time * 1000);
            }
        });
    });
}

 

2. 설명

1. 함수 CommandC는 C언어에 대한 코드를 수행한다.

2. 함수 CommandC의 매개변수 path, code, inputs, outputs, limit_time는 각각 코드를 저장할 file path, 사용자가 작성한 code, 테스트 케이스가 여러 개이므로 inputs[], 테스트 케이스에 대한 정답도 여러 개이므로 outputs, 제한시간 limit_time이다.

3. exec(compileCommand)는 사용자가 작성한 코드를 기반으로 컴파일하는 명령어이다.

4. complete 변수는 테스트케이스 inputs에 대한 정답 개수이며, complete와 inputs.length의 값이 같으면 모두 정답이므로 pass.

5.child = spwan(runCommand)로 컴파일이 완료된 프로그램을 실행하는 것이다.

6. child.stdin.write는 c프로그램 기준으로 scanf에 입력될 값을 보내는 것이고, child.stdin.end는 입력이 종료되었다는 문자 \0을 전송한다.

7. child.stdout.on('data')는 c프로그램 기준으로 출력된 값이 있을 때 발생하는 이벤트

8. clearTimeout은 제한시간 이내에 c프로그램이 종료되었을 때, setTimeout event loop를 종료하는 것이다. 

9. setTimeout(()=>{}, limit_time*1000) 은 제한시간이 지날 경우 c프로그램을 강제종료하는 것이다. ms단위이다.

 

3. 실행 결과

아래와 같이 backend에서 소스코드와 프로그램을 저장하고, spwan으로 실행하여 출력값을 얻은 뒤, pass/fail 판단 후 필요없는 파일은 삭제한다. 

소스코드는 필요시 DB 또는 file로 저장해도 무관하다.

 

나의 경우는 DB에 아래와 같이 저장한다.

반응형

댓글