나름 코딩에 관심이 있는 사람들은 한 번쯤 들어봤을 백준, BOJ!
자바스크립트 초심자들도 기웃기웃 했겠지만, 도대체 어떻게 사용하는지 몰라서 포기했던 적이 있지 않을까 싶다.
이에 자바스크립트로 백준에서 문제를 입력받고 푸는 방법에 대해 말해보고자 한다.
0. 언어는?
자바스크립트는 백준에서는 node.js를 선택하여 풀어야 한다.
내가 정말 자바스크립트만 공부하겠다, 하면 설정에서 언어모드를 'node.js'로 하는 것을 추천한다!
그러면 다른 문제 풀이를 볼 때 node.js만 보여준다.
만약 다른 언어도 병행한다면,,, 추천하지 않겠다.
1. 입력은 어떻게 받는 거죠?
입력을 받는 방법은, 백준의 가장 기본문제 1000번을 보면 알 수 있다.
https://www.acmicpc.net/problem/1000
1000번: A+B
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
www.acmicpc.net
문제 아래에 힌트가 있다. <<링크 클릭하셔요!
쭉 내리면 node.js가 있는데, 다른 언어와 달리 굉장히.. 복잡해 보인다!!
우선 입력받는 방식을 보면
var fs = require('fs');
var input = fs.readFileSync('/dev/stdin').toString().split(' ');
이렇게 받는다는 것을 알 수 있다.
그럼 require('fs')는 뭐고 그걸 왜 또 readFileSync()하며 안의 경로는 무엇인가!!
라는 고민이 생길 것이다. 하나하나 살펴보자~
1-1. require('fs')
require는 node.js에서 쓰이는, 모듈을 불러오는 방식이다, 즉 우리의 코드에 다른 코드를 불러오겠다는 것이다.
보통 다른 코드를 가져올 때는 require()메서드의 인자에 가져올 코드의 파일경로를 적어준다.
우리는 'fs' 모듈을 불러올 것이다. 따라서 require('fs')를 하게 되면, "나 fs 모듈을 불러올게~" 가 된다.
fs 모듈은, node.js에서 별도의 설치 없이 기본적으로 사용할 수 있는 모듈로서 File System의 약자이다..
즉 fs 모듈은 파일 처리와 관련된 전반적인 작업을 하는 모듈이다.
fs모듈에는 파일 처리와 관련된 여러가지 메서드가 존재하는데, fs 모듈에서 파일을 읽을 때 사용하는 메서드는 readFileSync()와 readFile()이 존재한다.
이 둘의 차이는 무엇이고, 백준에서는 왜 readFileSync()를 사용해야 할까?
1-2. readFileSync('/dev/stdin')
<< 여기 블로그를 참조하여 글을 작성했습니다 >>
https://balmostory.tistory.com/33
nodejs readFile과 readFileSync의 차이(비동기와 동기의 차이)
fs는 nodejs가 기본적으로 제공하는 filesystem이다. 파일을 불러오는 등의 기능을 제공한다. readFile과 readFileSync의 차이 reaFile로 파일을 다음과 같이 불러오면 어떤 결과가 나올까? test.json은 아래와
balmostory.tistory.com
readFile()와 readFileSync()의 차이는
- 파일을 읽고 나서 다음 코드를 실행하냐(readFileSync)
- 파일을 읽는 중에도 다음 코드를 계속 실행하냐(readFile)
의 차이다.
1-2-1. readFile()
내가 파일을 다 읽지 못해도 이미 다음 코드를 쭉쭉 실행한다(비동기적)
결국, 내가 파일을 다 읽기 전에 이미 다른 일들이 벌어지고 있다는 뜻이다.
const fs = require('fs');
fs.readFile('testText.txt','utf-8',(err,data)=>{
if (err) return console.log(err);
console.log(data);
})
console.log(`i'm second`);
같은 폴더에 testText.txt 파일을 만들고, 이를 비동기적(readFile)으로 읽으면 실행결과는 어떨까?
뭔가 한 줄씩 실행될 것 같지만, 아니다. 파일을 읽는 동안 이미 아랫줄을 실행해버린다.
<실행 결과>
1-2-2. readFileSync()
파일을 다 읽은 뒤에야 다음 코드를 실행한다. 코드 흐름의 싱크로가 맞으니까 sync라고 생각하자.(동기 방식)
const fs = require('fs');
console.log(fs.readFileSync('testText.txt','utf-8'))
console.log(`i'm second`);
아까의 testText.txt 를 활용했다. 이것을 readFileSync()로 읽게 되면?
파일을 다 읽을때까지 아래의 코드는 실행되지 않는다.
<실행 결과>
아직 input을 다 받지 못했는데 아래에 적은 코드들이 실행된다면, 에러가 발생할 것이다.
즉, 백준에서는 input으로 들어온 파일을 다 읽어야 문제를 풀 수 있기 때문에, readFileSync()방식을 이용해야 한다!
+ 그럼 readFileSync()안의 '/dev/stdin'는 뭐냐 할 수 있는데, 우리가 input으로 받을 값이 존재하는 경로라고 생각하면 된다. 백준의 채점 서버가 저쪽인가보다~ 하자.
완전 꿀팁인데, 매번 저것을 치기 귀찮으면 그냥 0을 적으면 된다
const fs = require('fs')
fs.readFileSync(0)
1-3. toString()
그럼 파일을 받아왔다면, 이를 문자열로 바꿔줘야 한다.
왜냐면 그냥 readFileSync(0)를 하면 Buffer 객체를 반환하기 때문이다.
위의 예시를 다시 이용해보자.
const fs = require('fs');
console.log(fs.readFileSync('testText.txt'));
<실행 결과>
우리가 알고 있는 문자가 아니라 아스키코드가 반환된 것을 알 수 있다...
따라서, 이것을 문자로 바꿔주는 toString() 메서드를 사용해야만 한다!
const fs = require('fs');
console.log(fs.readFileSync('testText.txt').toString());
<실행 결과>
하지만, toString()을 사용하지 않는 방법도 있다.
readFileSync에서 두 번째 매개변수는 option인데, 이 곳에 'utf-8'을 입력하면 알아서 인코딩해준다.
const fs = require('fs');
console.log(fs.readFileSync('testText.txt', 'utf8'));
<실행 결과> ➡️ toString()메서드를 사용했을 때와 동일한 결과
우선 기본적으로 해야하는 것은
- const fs = require('fs')
- fs.readFileSync('/dev/stdin') ➡️ readFileSync(0)으로 표현 가능!
- fs.readFileSync('/dev/stdin').toString() ➡️ fs.readFileSync('/dev/stdin', 'utf-8')로 표현 가능!
이 모든 요소를 종합하여 한 줄로 표현할 수 있다.
require('fs').readFileSync(0, 'utf-8')
이 이후에 split이나 trim이나 map 메서드 등등은, 상황에 따라 적으면 된다.
단, trim() 메서드는 웬만하면 사용하길 바란다!!
이후에 문제를 풀다 보면, reference error가 뜰 때가 많은데, input값에 \n과 같이 우리가 사용하지 않을 값이 들어가서 그런 경우가 대부분이다. 이럴땐 trim()을 이용하여 불필요한 input이 없도록 해야한다.
2. 출력은요?
출력은 console.log()를 이용한다.
출력할 값을 로그로 찍으면 성공!
'개발 > 알고리즘' 카테고리의 다른 글
[프로그래머스] 혼자 놀기의 달인 (javascript) (0) | 2024.08.27 |
---|