[단계별로 풀어보기-Java] 3단계 반복문 (+ EOF 처리)
안녕하세요 오늘은 백준 3단계를 푸는 날입니다 ~!!
반복문 단계라서 주로 for문을 사용해서 풀었고,
마지막 문제는 EOF 처리에 대해 설명을 적어놨으니 확인해주세요 ✌️
✏️ 문제 번호 : 2739
구구단
N을 입력받은 뒤, 구구단 N단을 출력하는 프로그램을 작성하시오. 출력 형식에 맞춰서 출력하면 된다.
입력
첫째 줄에 N이 주어진다. N은 1보다 크거나 같고, 9보다 작거나 같다.
출력
출력형식과 같게 N*1부터 N*9까지 출력한다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
for(int i=1; i<10; i++){
System.out.println(N+" * "+i+" = "+N*i);
}
}
}
✏️ 문제 번호 : 10950
A+B-3
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다.
각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력
각 테스트 케이스마다 A+B를 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder(); // 결과를 저장할 StringBuilder 생성
for (int i =0; i<T; i++){
String[] input = br.readLine().split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
sb.append(a + b).append("\n"); // 결과를 StringBuilder에 저장
}
System.out.print(sb.toString());
}
}
문제 풀이
테스트케이스 T를 첫 줄에 받아온 후, T의 개수에 만큼 for문을 순회합니다.
a, b를 입력할 때마다 결과를 StringBuilder에 저장 해 놓습니다.
StringBuilder를 사용하면 메모리 사용량과 성능 면에서 반복적인 문자열 연결보다 효율적이므로 사용하게 됐습니다.
반복이 끝난 후, StringBuilder에 저장된 내용을 한꺼번에 출력합니다.
✏️ 문제 번호 : 8393
합
n이 주어졌을 때, 1부터 n까지 합을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 n (1 ≤ n ≤ 10,000)이 주어진다.
출력
1부터 n까지 합을 출력한다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int sum = 0;
for (int i=1; i<=n; i++){
sum+=i;
}
System.out.print(sum);
sc.close();
}
}
✏️ 문제 번호 : 25304
영수증
준원이는 저번 주에 살면서 처음으로 코스트코를 가 봤다. 정말 멋졌다. 그런데, 몇 개 담지도 않았는데 수상하게 높은 금액이 나오는 것이다! 준원이는 영수증을 보면서 정확하게 계산된 것이 맞는지 확인해보려 한다.
영수증에 적힌,
- 구매한 각 물건의 가격과 개수
- 구매한 물건들의 총 금액
을 보고, 구매한 물건의 가격과 개수로 계산한 총 금액이 영수증에 적힌 총 금액과 일치하는지 검사해보자.
입력
첫째 줄에는 영수증에 적힌 총 금액 X가 주어진다.
둘째 줄에는 영수증에 적힌 구매한 물건의 종류의 수 N이 주어진다.
이후 N개의 줄에는 각 물건의 가격 a와 개수 b가 공백을 사이에 두고 주어진다.
출력
구매한 물건의 가격과 개수로 계산한 총 금액이 영수증에 적힌 총 금액과 일치하면 Yes를 출력한다.
일치하지 않는다면 No를 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int X = Integer.parseInt(br.readLine());
int N = Integer.parseInt(br.readLine());
int total = 0;
for (int i = 0; i < N; i++) {
String[] input = br.readLine().split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
total += a * b;
}
if(total == X) {
System.out.print("Yes");
}
else {
System.out.print("No");
}
}
}
✏️ 문제 번호 : 25314
코딩은 체육과목 입니다
오늘은 혜아의 면접 날이다. 면접 준비를 열심히 해서 앞선 질문들을 잘 대답한 혜아는 이제 마지막으로 칠판에 직접 코딩하는 문제를 받았다. 혜아가 받은 문제는 두 수를 더하는 문제였다. C++ 책을 열심히 읽었던 혜아는 간단히 두 수를 더하는 코드를 칠판에 적었다. 코드를 본 면접관은 다음 질문을 했다. “만약, 입출력이 N바이트 크기의 정수라면 프로그램을 어떻게 구현해야 할까요?”
혜아는 책에 있는 정수 자료형과 관련된 내용을 기억해 냈다.
책에는 long int는 4바이트 정수까지 저장할 수 있는 정수 자료형이고 long long int는 8바이트 정수까지 저장할 수 있는 정수 자료형이라고 적혀 있었다.
혜아는 이런 생각이 들었다. “int 앞에 long을 하나씩 더 붙일 때마다 4바이트씩 저장할 수 있는 공간이 늘어나는 걸까? 분명 long long long int는 12바이트, long long long long int는 16바이트까지 저장할 수 있는 정수 자료형일 거야!” 그렇게 혜아는 당황하는 면접관의 얼굴을 뒤로한 채 칠판에 정수 자료형을 써 내려가기 시작했다.
혜아가 N바이트 정수까지 저장할 수 있다고 생각해서 칠판에 쓴 정수 자료형의 이름은 무엇일까?
입력
첫 번째 줄에는 문제의 정수 N이 주어진다. (4 ≤ N ≤ 1000;
출력
혜아가 N바이트 정수까지 저장할 수 있다고 생각하는 정수 자료형의 이름을 출력하여라.
문제 풀이
문제를 풀기 전, 규칙을 찾아보겠습니다.
long int는 4바이트
long long int는 8바이트
long long long int는 12바이트
long long long long int는 16바이트
이렇게 4의 배수로 바이트가 증가하는 것을 확인할 수 있고,
예제 입력 2에서 '20'을 입력한 경우는 4의 배수에 5를 곱한 값입니다.
또한, 값이 1씩 증가할 때마다 long이 출력값 앞에 하나씩 더 붙는 형태이고,
N은 4의 배수이므로 반복문 조건식에 N/4을 해줍니다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
StringBuilder result = new StringBuilder();
// N / 4 만큼 "long"을 추가
for (int i = 0; i < N / 4; i++) {
result.append("long ");
}
result.append("int");
System.out.println(result.toString());
}
}
✏️ 문제 번호 : 15552
빠른 A+B
본격적으로 for문 문제를 풀기 전에 주의해야 할 점이 있다.
입출력 방식이 느리면 여러 줄을 입력받거나 출력할 때 시간초과가 날 수 있다는 점이다.
C++을 사용하고 있고 cin/cout을 사용하고자 한다면, cin.tie(NULL)과 sync_with_stdio(false)를 둘 다 적용해 주고, endl 대신 개행문자(\n)를 쓰자.
단, 이렇게 하면 더 이상 scanf/printf/puts/getchar/putchar 등 C의 입출력 방식을 사용하면 안 된다.
Java를 사용하고 있다면, Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용할 수 있다. BufferedWriter.flush는 맨 마지막에 한 번만 하면 된다.
Python을 사용하고 있다면, input 대신 sys.stdin.readline을 사용할 수 있다. 단, 이때는 맨 끝의 개행문자까지 같이 입력받기 때문에 문자열을 저장하고 싶을 경우 .rstrip()을 추가로 해 주는 것이 좋다.
또한 입력과 출력 스트림은 별개이므로, 테스트케이스를 전부 입력받아서 저장한 뒤 전부 출력할 필요는 없다. 테스트케이스를 하나 받은 뒤 하나 출력해도 된다.
자세한 설명 및 다른 언어의 경우는 이 글에 설명되어 있다.
이 블로그 글에서 BOJ의 기타 여러 가지 팁을 볼 수 있다.
입력
첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.
출력
각 테스트케이스마다 A+B를 한 줄에 하나씩 순서대로 출력한다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int T = Integer.parseInt(br.readLine()); // 테스트 케이스 개수 입력
for (int i = 0; i < T; i++) {
String[] input = br.readLine().split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
bw.write((a + b) + "\n"); // 결과를 BufferedWriter에 저장
}
bw.flush(); // 버퍼에 남아 있는 데이터를 출력
bw.close();
br.close();
}
}
문제 풀이
문제에서 요구하는 조건이
BufferedReader와 BufferedWriter.flush()을 적용해서 푸는 것이다.
여기서 flush는 출력 버퍼에 쌓인 데이터를 한꺼번에 출력하는 역할을 합니다.
매번 호출하면 출력 작업이 늘어나 I/O 병목이 발생하므로, 마지막에 한 번만 호출하는 것이 성능 면에서 유리합니다.
✏️ 문제 번호 : 11021
A+B-7
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다.
각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력
각 테스트 케이스마다 "Case #x: "를 출력한 다음, A+B를 출력한다.
테스트 케이스 번호는 1부터 시작한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
int[] result = new int[T];
for (int i =0; i<T; i++){
String[] input = br.readLine().split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
result[i] = a+b;
sb.append("Case #"+(i+1)+": "+result[i]+"\n");
}
System.out.print(sb.toString());
}
}
✏️ 문제 번호 : 11022
A+B-8
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다.
각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력
각 테스트 케이스마다 "Case #x: A + B = C" 형식으로 출력한다.
x는 테스트 케이스 번호이고 1부터 시작하며, C는 A+B이다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
int[] result = new int[T];
for (int i =0; i<T; i++){
String[] input = br.readLine().split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
result[i] = a+b;
sb.append("Case #"+(i+1)+": "+a+" + "+b+" = "+result[i]+"\n");
}
System.out.print(sb.toString());
}
}
✏️ 문제 번호 : 2438
별 찍기 -1
첫째 줄에는 별 1개, 둘째 줄에는 별 2개, N번째 줄에는 별 N개를 찍는 문제
입력
첫째 줄에 N(1 ≤ N ≤ 100)이 주어진다.
출력
첫째 줄부터 N번째 줄까지 차례대로 별을 출력한다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
System.out.print("*");
}
System.out.println();
}
sc.close();
}
}
✏️ 문제 번호 : 2439
별 찍기 -2
첫째 줄에는 별 1개, 둘째 줄에는 별 2개, N번째 줄에는 별 N개를 찍는 문제
하지만, 오른쪽을 기준으로 정렬한 별(예제 참고)을 출력하시오.
입력
첫째 줄에 N(1 ≤ N ≤ 100)이 주어진다.
출력
첫째 줄부터 N번째 줄까지 차례대로 별을 출력한다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n-i; j++) {
System.out.print(" ");
}
for (int k=1; k<=i; k++) {
System.out.print("*");
}
System.out.println();
}
sc.close();
}
}
✏️ 문제 번호 : 10952
A+B-5
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 이루어져 있다.
각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 A와 B가 주어진다. (0 < A, B < 10)
입력의 마지막에는 0 두 개가 들어온다.
출력
각 테스트 케이스마다 A+B를 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
while(true){
String[] input = br.readLine().split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
if(a==0 && b==0){
break;
}
sb.append((a+b)+"\n");
}
System.out.print(sb.toString());
}
}
✏️ 문제 번호 : 10951
A+B-4
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.
입력
입력은 여러 개의 테스트 케이스로 이루어져 있다.
각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 A와 B가 주어진다. (0 < A, B < 10)
출력
각 테스트 케이스마다 A+B를 출력한다.
위 문제는 간단한 문제처럼 보이지만, 종료 시점(EOF)을 처리하는 부분에서 의외로 많은 사람이 틀리게 되는 경우가 있습니다. 이 글에서는 EOF(End of File)를 처리하는 방법과 이를 활용한 코드를 작성하는 방법을 소개하겠습니다.
주의 사항
1. 두 정수는 공백으로 나뉘어 구분됩니다.
입력받은 한 줄을 공백으로 나누어 A와 B를 처리해야 합니다.
2. 입력의 종료는 EOF(End of File)로 처리됩니다.
EOF는 더 이상 읽을 데이터가 없을 때 반복문을 종료하도록 설정합니다.
EOF 란?
입력 스트림에서 더 이상 읽을 수 있는 데이터가 없을 때를 의미합니다.
파일이나 표준 입력(콘솔)에서 데이터를 읽는 프로그램은 EOF를 만나면 반복적으로 읽는 작업을 멈춥니다.
EOF의 처리 방식
Java에서 EOF를 처리하려면 BufferedReader.readLine() 메서드를 사용합니다.
readLine() 메서드는 입력이 더 이상 없을 때 null을 반환하므로, 이를 반복문 종료 조건으로 사용합니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) { // EOF 처리
String[] input = line.split(" ");
int a = Integer.parseInt(input[0]);
int b = Integer.parseInt(input[1]);
sb.append(a + b).append("\n");
}
System.out.print(sb.toString());
}
}
문제 풀이
위 코드에 대해 설명하자면,
입력 처리는 BufferedReader.readLine()을 사용하여 한 줄씩 데이터를 읽고, 더 이상 읽을 데이터가 없으면 null을 반환하는 것을 이용합니다. 반복문 조건으로 while ((line = br.readLine()) != null)을 설정해 입력이 존재하는 동안만 실행되며, 종료 시 반복문이 끝납니다.
출력 처리는 StringBuilder를 활용해 각 계산 결과를 저장한 뒤, 반복문이 끝난 후 한꺼번에 출력하여 효율성을 높입니다.
이 방식은 EOF를 명확히 처리하며 콘솔과 파일 입력 모두에 적용 가능하고, 반복적인 I/O 작업을 최소화해 성능을 향상시킵니다. 단, 입력 데이터 형식을 준수하지 않을 경우 예외가 발생할 수 있으므로 형식 검증이 중요합니다.
이처럼 오늘도 백준 3단계를 풀어봤습니다.
저는 내일 4단계 문제 풀이로 돌아오겠습니다 😉
오코완
(오늘도 코테 공부 완료)