코딩 테스트 연습할 때 프로그래머스를 주로 사용하여 연습하였다.
프로그래머스를 사용한 제일 큰 이유는 입력이 함수의 매개변수로 들어와서 문제 풀기가 쉽기 때문이다.
하지만 백준싸이트에서 입력을 코드로 직접 받아야 한다. 직접 받는 게 무슨 문제냐고 할 수 있지만 다른 언어에 비해 javascript는 백준에서 입력을 받기가 조금 까다롭다.
그래서 백준을 포기하고 프로그래머스를 사용했는데 이제 조금 더 다양한 문제를 풀기 위해 백준에 도전하려고 한다.
입력을 어떻게 받아야할지 많이 찾아보았는데 아래의 유튜브에서 초보자들이 하기에 잘 정리해주었다. 아래의 영상을 보고 이 글을 작성하기로 했다.
초보자가 자바스크립트로 백준 문제 푸는 법
추가내용
1
const fs = require("fs");
const filePath = process.platform === "linux" ? "/dev/stdin" : "./input.txt";
let input = fs.readFileSync(filePath).toString().split("\n");
위 코드로 input 값을 받아오면 vscode에서는 input.txt로 받을 수 있고
백준같은 리눅스 환경에서는 /dev/stdin으로 받을 수 있다.
2
Node.js 온라인 컴파일러
vsCode에서는 정답인 문제가 백준에서 틀리는 경우가 종종있다.
위 환경은 백준과 같은 리눅스 환경이라 정확히 테스트를 해볼 수 있다.
위 싸이트의 stdin Inuts
에 백준 입력 예제를 넣고 테스트해보기 바란다.
3
toString()으로 문자열을 받을 때
const fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().trim();
문자열을 toString()으로 변환하여 받을 때에는 양끝에 불필요한 줄바꿈 문자가 남을 수 있다.
이것을 trim()으로 처리하여 저장하자!
vscode로 문제를 푸는 방법이다.
아래의 문제를 예시로 들겠다.
https://www.acmicpc.net/problem/4344
준비
node.js
: 설치되어 있어야 브라우저 없이 vscode에서 javascript를 돌릴 수 있다.vscode
: 이거로 코드를 작성할 것이다.
1.input 파일 및 File System 모듈
위 사진 처럼 input 파일을 만들어서 js 폴더와 같은 위치에 둔다.
파일명은 개인이 정하면 된다. 필자는 input.txt
로 하였다.
const fs = require("fs");
let input = fs.readFileSync("./input.txt").toString();
File System을 위와 같이 불러온다.fs
에는 File System 모듈을 가져오는 것이다.input
에는 input.txt
파일의 값을 string으로 변환하는 것이다.
이렇게 불러오면 아래와 같이 출력된다.
5
5 50 50 70 80 100
7 100 95 90 80 70 60 50
3 70 90 80
3 70 90 81
9 100 99 98 97 96 95 94 93 91
이렇게 가져온 입력을 바로 사용할 수 없다.
문제에 적용할 수 있게 변환하여 정제하는 과정이 필요한다.
2. input값 변환하기
const fs = require("fs");
let input = fs.readFileSync("./input.txt").toString();
input = input.split("\n");
const inputC = +input[0];
const inputTestCase = [];
for (let i = 1; i <= inputC; ++i) {
const arr = input[i].split(" ").map((item) => +item);
let newArr = [];
for (let j = 1; j < arr.length; j++) {
newArr.push(arr[j]);
}
const testCase = {
N: arr[0],
arr: newArr,
};
inputTestCase.push(testCase);
}
2-1 라인별 풀이
문제를 풀기 위해 위와 같이 input 값을 변환하였다.
input = input.split("\n");
일단 위의 입력을 줄을 기준으로 나눠서 배열에 저장한다.
[
'5\r',
'5 50 50 70 80 100\r',
'7 100 95 90 80 70 60 50\r',
'3 70 90 80\r',
'3 70 90 81\r',
'9 100 99 98 97 96 95 94 93 91'
]
이러한 값이 출력된다. \r
은 환경에 따라 출력될 수도 있고 안될 수도 있다.
유튜브에서는 \r
이 나오지 않았지만 나의 환경에서는 출력되었다.
이걸 자른다고 split('\r\n')
으로 코드를 작성하면 백준에서는 틀렸다고 나온다.
그러니 \n
으로 한줄씩 자르고 \r 은 무시한다.
const inputC = +input[0];
문제에서 테스트 케이스의 개수 C를 따로 저장하는 변수이다.
input[0]은 문자열임으로 + 단항 연산자를 사용하여 number로 변환하여 저장한다.
for (let i = 1; i <= inputC; ++i)
제일 첫 줄 inputC를 제외하고 나머지 줄을 for문을 돌린다.
const arr = input[i].split(" ").map((item) => +item);
arr는 한 줄의 입력값을 따로 배열에 저장한다.
첫 번째 줄로 예시를 들면 [ 5, 50, 50, 70, 80, 100 ]
이런 배열로 arr에 저장된다.
let newArr = [];
for (let j = 1; j < arr.length; j++) {
newArr.push(arr[j]);
}
arr의 첫번째 학생의 수를 제외한 입력된 점수를 따로 newArr에 저장하기에 j는 1부터 시작한다.
const testCase = {
N: arr[0],
arr: newArr,
};
inputTestCase.push(testCase);
testCaser에 N은 학생의 수를 arr는 점수의 배열을 넣은 객체로 만들어 inputTestCase 배열에 push 한다.
이렇게 정재를 거치면 아래와 같이 배열에 저장된다.
[
{ N: 5, arr: [ 50, 50, 70, 80, 100 ] },
{ N: 7, arr: [
100, 95, 90, 80,
70, 60, 50
] },
{ N: 3, arr: [ 70, 90, 80 ] },
{ N: 3, arr: [ 70, 90, 81 ] },
{
N: 9,
arr: [
100, 99, 98, 97, 96,
95, 94, 93, 91
]
}
]
이제 프로그래머스처럼 풀 수 있게 함수로 넘겨줄 값이 완성되었다
3. 문제 풀이 세팅
solution(inputC, inputTestCase);
function solution(C, inputTestCase){
/**
* 문제 풀이
*/
}
solution이란 함수를 작성하고 위에서 변환한 input값을 매개변수로 넘겨주면 된다.
이렇게 하면 solution함수에서 문제 풀이에 집중하여 풀 수 있다.
4. 정답 제출
const fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString(); //<-
input = input.split("\n");
const inputC = +input[0];
const inputTestCase = [];
for (let i = 1; i <= inputC; ++i) {
const arr = input[i].split(" ").map((item) => +item);
let newArr = [];
for (let j = 1; j < arr.length; j++) {
newArr.push(arr[j]);
}
const testCase = {
N: arr[0],
arr: newArr,
};
inputTestCase.push(testCase);
}
solution(inputC, inputTestCase);
function solution(C, inputTestCase) {
/**
* 문제 풀이
*/
console.log("정답출력");
}
문제를 다 풀었다는 가정하에 백준에 정답을 제출하기 전에 변경해야 할 것이 있다.let input = fs.readFileSync("input.txt").toString();
를 아래로 변경한다.let input = fs.readFileSync("/dev/stdin").toString();
readFileSync에 '/dev/stdin'를 넣어야 백준에서 입력값을 받을 수 있다.
그리고 백준의 정답 출력은 프로그래머스처럼 return으로 하는 것이 아닌
console.log로 정답을 출력하면 된다.
위 문제는 하나의 예시이다.
문제마다 입력값을 변환하는 과정은 다를 것이다.
그리고 문제 풀기도 바쁜데 입력값도 만들어야 하나 라는 생각이 들 수 있다.
입력값을 만드는 과정도 하나의 연습이라 생각하고 문제를 풀어보자!
글이 이해가 안 된다면 영상을 보고 해 보시기 바란다!
'지난 글 모음' 카테고리의 다른 글
[백준 node.js] 10870번 피보나치 수5 JavaScript (0) | 2022.02.02 |
---|---|
[백준 node.js] 1032번 명령 프롬프트 JavaScript (0) | 2022.01.31 |
[프로그래머스] LV1 다트게임 JavaScript (0) | 2022.01.29 |
[프로그래머스] LV2 메뉴 리뉴얼 JavaScript (0) | 2022.01.27 |
[React Hooks] input onChange 사용법 (onChange)사용 예시 (0) | 2022.01.26 |