내가 생각했을때 문제에서 원하는부분
첫 번째 줄에 즐기는 것의 개수 N이 주어진다.
뒤의 N개 줄에는 즐기는 것의 이름이 모두 영어 대문자와 띄어쓰기로 적혀 있다.
이는 30자를 넘지 않는다.
각 줄에 인생 점수를 입력받은 대로 출력한다.
만약 100점이라면 100 대신 "PERFECT LIFE" 를 출력한다.
내가 이 문제를 보고 생각해본 부분
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));:
System.in은 키보드와 같은 표준 입력 장치로부터 바이트 단위로 데이터를 읽어오는 스트림입니다.
new InputStreamReader(System.in)을 통해 바이트 스트림인 System.in을 문자 스트림으로 변환합니다.
변환된 문자 스트림을 new BufferedReader(...)의 인자로 넘겨주어 BufferedReader 객체 br을 생성합니다. 이제 br을 통해 키보드 입력을 효율적으로 읽을 수 있습니다.
StringBuilder sb = new StringBuilder();:
StringBuilder는 문자열을 효율적으로 다루기 위한 클래스입니다. 자바에서 문자열(String)은 불변(immutable) 객체이기 때문에, + 연산자로 문자열을 계속 이어 붙이면 매번 새로운 String 객체가 생성되어 메모리 사용량과 성능에 좋지 않습니다.
StringBuilder는 가변(mutable) 객체이므로, append() 메서드를 사용하여 문자열을 추가할 때 새로운 객체를 생성하지 않고 내부 버퍼를 확장하여 처리하므로 훨씬 효율적입니다. 여기서는 계산된 결과를 하나씩 sb에 모아둔 다음, 마지막에 한 번에 출력하기 위해 사용합니다.
int N = Integer.parseInt(br.readLine());:
br.readLine(): BufferedReader를 사용하여 표준 입력에서 한 줄을 읽어 문자열로 반환합니다. 이 문제에서는 첫 번째 줄에 주어지는 즐기는 것의 개수 N을 읽습니다.
Integer.parseInt(): br.readLine()이 반환한 문자열("4" 등)을 실제 정수(4)로 변환합니다. 이 정수 N은 몇 번 반복하여 다음 줄들을 처리할지 결정하는 데 사용됩니다.
for (int i = 0; i < N; i++) { ... } (메인 반복문):
N은 처리해야 할 즐기는 것의 개수입니다. 이 for 반복문은 0부터 N-1까지 N번 실행되면서 각 즐기는 것에 대한 점수를 계산하고 출력 형식을 결정합니다.
String line = br.readLine();:
메인 반복문 안에서 매번 새로운 줄(예: "OTAKU LIFE", "PRODUCER" 등)을 읽어와 line이라는 String 변수에 저장합니다.
int score = 0;:
각 line에 대한 점수를 계산하기 전에 score 변수를 0으로 초기화합니다. 이렇게 해야 다음 line의 점수를 정확히 다시 계산할 수 있습니다.
for (char c : line.toCharArray()) { ... } (문자열 순회):
이것은 향상된 for 문(for-each 문)입니다.
line.toCharArray(): 현재 line 문자열을 char 타입의 배열로 변환합니다. 예를 들어, "OTAKU"는 ['O', 'T', 'A', 'K', 'U'] 배열이 됩니다.
for (char c : ...): 이 배열의 각 문자(char)를 순서대로 c 변수에 할당하며 반복문을 실행합니다. 이 방식은 문자열의 모든 문자에 대해 작업을 수행할 때 편리합니다.
if (c == ' ') { continue; } (띄어쓰기 처리):
현재 문자인 c가 띄어쓰기인지 확인합니다.
만약 띄어쓰기라면, continue 키워드를 사용하여 현재 반복을 즉시 중단하고 다음 문자로 넘어갑니다. 이는 띄어쓰기를 점수 계산에서 제외하라는 문제의 요구사항을 반영합니다.
score += (c - 'A' + 1); (알파벳 점수 계산):
이 부분이 알파벳을 점수로 변환하는 핵심 로직입니다.
자바에서 char 타입은 내부적으로 아스키(ASCII) 또는 유니코드(Unicode) 값을 가집니다. 'A'는 65, 'B'는 66, ..., 'Z'는 90의 아스키 값을 가집니다.
c - 'A': 현재 문자 c의 아스키 값에서 'A'의 아스키 값을 빼면, c가 'A'로부터 얼마나 떨어져 있는지 알 수 있습니다.
'A' - 'A' = 0
'B' - 'A' = 1
'Z' - 'A' = 25
... + 1: 문제에서 'A'를 1점, 'B'를 2점 등으로 정의했으므로, 위 결과에 1을 더해줍니다.
'A' 점수: (0) + 1 = 1점
'B' 점수: (1) + 1 = 2점
'Z' 점수: (25) + 1 = 26점
score += ...: 계산된 점수를 score 변수에 누적하여 더합니다.
if (score == 100) { ... } else { ... } (출력 형식 결정):
하나의 line에 대한 모든 문자 순회가 끝나면, 최종 score 값을 확인합니다.
if (score == 100): 만약 score가 정확히 100점이라면, sb.append("PERFECT LIFE").append("\n");를 통해 "PERFECT LIFE" 문자열과 줄바꿈(\n)을 StringBuilder에 추가합니다.
else: 100점이 아니라면, sb.append(score).append("\n");를 통해 계산된 숫자 score를 문자열로 변환하여 StringBuilder에 추가합니다. 이때 sb.append(score)는 score를 자동으로 문자열로 변환해 줍니다. 마찬가지로 줄바꿈(\n)도 추가합니다.
System.out.print(sb.toString());:
for 반복문이 모두 끝나면, StringBuilder sb에 N개의 줄에 대한 모든 결과가 저장되어 있습니다.
sb.toString(): StringBuilder의 내용을 최종 String으로 변환합니다.
System.out.print(): 변환된 String을 한 번에 표준 출력(콘솔)으로 출력합니다. 이렇게 한 번에 출력하는 방식은 System.out.println()을 N번 호출하는 것보다 입출력 오버헤드를 줄여 효율적입니다.
br.close();:
BufferedReader와 같은 자원(resource)은 사용 후 반드시 닫아주어야 합니다.
코드로 구현
package baekjoon.baekjoon_30;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
// 백준 15351번 문제
public class Main1144 {
public static void main(String[] args) throws IOException {
// BufferedReader: 대량의 입력을 효율적으로 처리할 때 사용합니다.
// InputStreamReader: System.in(표준 입력)은 바이트 스트림이므로,
// 문자 단위로 읽기 위해 이를 문자 스트림으로 변환해 줍니다.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// StringBuilder: 여러 문자열을 반복적으로 연결할 때 효율적입니다.
// System.out.println을 N번 호출하는 대신, 결과를 한 번에 모아서 출력합니다.
StringBuilder sb = new StringBuilder();
// 첫 번째 줄에서 즐기는 것의 개수 N을 읽어옵니다.
// br.readLine()은 문자열을 반환하므로, Integer.parseInt()를 사용하여 정수로 변환합니다.
int N = Integer.parseInt(br.readLine());
// N번 반복하여 각 즐기는 것의 이름을 처리합니다.
for(int i = 0; i < N; i++) {
// 한 줄(즐기는 것의 이름)을 문자열로 읽어옵니다.
String line = br.readLine();
// 각 문자열의 인생 점수를 저장할 변수를 초기화합니다.
int score = 0;
// 문자열을 char 배열로 변환하여 각 문자를 순회합니다.
// 이렇게 하면 문자열의 각 문자에 쉽게 접근할 수 있습니다.
for(char c : line.toCharArray()) {
// 현재 문자가 띄어쓰기(' ')인지 확인합니다.
if(c == ' ') {
// 띄어쓰기라면 점수 계산에서 제외하고 다음 문자로 넘어갑니다.
continue;
}
// 알파벳 'A'는 아스키코드 65, 'B'는 66 ... 입니다.
// 문제에서 'A'를 1점, 'B'를 2점으로 정의했으므로,
// 'A'를 기준으로 한 위치 값에 1을 더하면 됩니다.
// 예: 'A' - 'A' + 1 = 0 + 1 = 1점
// 예: 'B' - 'A' + 1 = 1 + 1 = 2점
score += (c - 'A' + 1);
}
// 모든 문자의 점수 계산이 끝난 후, 최종 점수를 확인합니다.
if(score == 100) {
// 점수가 100점이라면 "PERFECT LIFE" 문자열을 StringBuilder에 추가합니다.
sb.append("PERFECT LIFE").append("\n"); // 줄바꿈 문자도 추가합니다.
} else {
// 100점이 아니라면 계산된 점수 숫자를 StringBuilder에 추가합니다.
sb.append(score).append("\n"); // 줄바꿈 문자도 추가합니다.
}
}
// 모든 계산이 끝난 후, StringBuilder에 모아둔 결과를 한 번에 출력합니다.
System.out.print(sb.toString());
// BufferedReader 사용이 끝났으므로 닫아줍니다.
br.close();
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.