
내가 생각했을때 문제에서 원하는부분
첫째 줄부터 최대 100개의 줄에 알파벳 대문자로 이루어진 해석해야 할 문장이 주어진다.
문장의 길이는 10^4이하인 자연수이다.
해석해야 할 문장이 모두 주어진 후, 마지막 문장은 Was it a cat I saw? 로 주어지고, 마지막 문장은 해석하지 않는다.
한 줄에 한 문장씩 해당 줄의 문장에서 해석한 암호를 출력한다.
내가 이 문제를 보고 생각해본 부분
초기 설정:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));: 위에서 설명했듯이, 표준 입력(콘솔)으로부터 효율적으로 텍스트를 읽어올 수 있도록 BufferedReader 객체를 생성한다.
StringBuilder sb = new StringBuilder();: 해독된 결과 문자열들을 하나씩 추가하여 최종적으로 한 번에 출력하기 위해 StringBuilder를 사용한다.
일반 String 객체는 내용을 변경할 때마다 새로운 객체를 생성하지만, StringBuilder는 내부 버퍼를 조작하여 문자열 변경이 잦은 경우 훨씬 효율적이다.
int lineNumber = 0;: 현재 처리 중인 암호문 라인의 번호를 기록하는 변수이다.
문제에서 i번째 줄이라고 했으니, 이 lineNumber가 i의 역할을 하게 된다.
초기값은 0이지만, 첫 줄을 읽을 때 1로 증가하여 사용된다.
암호문 처리 반복문:
while(true): 입력의 끝을 알 수 없기 때문에, 무한 루프를 사용하여 한 줄씩 암호문을 계속 읽는다.
String line = br.readLine();: BufferedReader를 사용하여 한 줄의 암호문을 읽어 line 변수에 저장한다.
if(line == null || line.equals("Was it a cat I saw?")) { break; }: 이 부분이 반복문을 종료하는 조건이다.
line == null: 더 이상 읽어들일 입력이 없는 경우(파일의 끝 등) readLine()은 null을 반환한다.
line.equals("Was it a cat I saw?"): 문제에서 제시된 특별한 종료 문자열이 입력된 경우, 이 문자열은 해독하지 않고 반복문을 종료한다.
lineNumber++;: 유효한 암호문 라인을 읽었으므로, 라인 번호를 1 증가시킨다.
이제 lineNumber는 현재 암호문이 몇 번째 줄인지 정확히 나타낸다.
개별 암호문 해독 로직:
StringBuilder decryptedMessage = new StringBuilder();: 현재 줄의 암호문에서 해독된 글자들을 임시로 모으기 위한 StringBuilder이다.
매 줄마다 새로 생성되어 사용된다.
int step = lineNumber + 1;: 문제의 핵심 해독 규칙을 적용하는 부분이다.
i번째 줄은 i칸씩 건너뛰며 읽어야 한다고 했고, lineNumber가 현재 i 역할을 하므로, 실제로 글자를 건너뛸 간격은 lineNumber + 1이 된다. (첫 글자부터 시작, 1칸 건너뛸 경우 2칸마다)
for(int j = 0; j < line.length(); j += step): 이 for 반복문이 실제 해독을 수행한다.
j = 0: 암호문의 첫 글자(인덱스 0)부터 시작한다.
j < line.length(): line 문자열의 끝까지 반복한다.
j += step: j를 step만큼 증가시켜 다음 해독할 글자의 인덱스로 건너뛴다.
decryptedMessage.append(line.charAt(j));: line 문자열에서 현재 j 인덱스에 해당하는 문자를 decryptedMessage에 추가한다.
sb.append(decryptedMessage.toString()).append("\n");: 한 줄의 암호문 해독이 끝나면, decryptedMessage에 모인 글자들을 문자열로 변환한 후, 마지막 결과 StringBuilder인 sb에 추가하고 줄바꿈 문자(\n)도 함께 추가하여 다음 해독 결과를 새 줄에 출력할 수 있도록 한다.
결과 출력 및 자원 해제:
System.out.print(sb.toString());: while 루프가 모두 종료되면, sb에 최종적으로 모인 모든 해독된 메시지들을 한 번에 표준 출력으로 출력한다.
println 대신 print를 사용하고 \n을 직접 추가하는 것은 println이 OS마다 다른 줄바꿈 문자를 사용할 수 있는 경우를 방지하고, 출력 제어를 더 명확하게 하기 위함이다.
br.close();: BufferedReader 사용이 끝났으므로, 시스템 자원을 효율적으로 관리하기 위해 close() 메서드를 호출하여 사용했던 자원을 반환한다.
코드로 구현
package baekjoon.baekjoon_31;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
// 백준 18245번 문제
public class Main1210 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder(); // 최종 결과를 모아서 출력하기 위한 StringBuilder
int lineNumber = 0; // 현재 처리 중인 라인의 번호 (1부터 시작)
while(true) { // 입력이 끝날 때까지 반복
String line = br.readLine(); // 한 줄을 읽어옵니다.
// 입력 종료 조건: null이거나 특정 문자열("Was it a cat I saw?")인 경우 반복을 종료합니다.
if(line == null || line.equals("Was it a cat I saw?")) {
break;
}
lineNumber++; // 라인 번호를 1 증가시킵니다.
StringBuilder decryptedMessage = new StringBuilder(); // 현재 줄의 해독된 메시지를 저장할 StringBuilder
int step = lineNumber + 1; // 건너뛸 간격 (i+1)
// 암호문의 첫 글자부터 시작하여 'step' 간격으로 글자를 선택합니다.
for(int j = 0; j < line.length(); j += step) {
decryptedMessage.append(line.charAt(j)); // 해당 인덱스의 글자를 decryptedMessage에 추가
}
// 해독된 메시지와 줄바꿈 문자를 최종 결과 StringBuilder에 추가합니다.
sb.append(decryptedMessage.toString()).append("\n");
}
// 모든 해독된 메시지를 한 번에 출력합니다.
System.out.print(sb.toString());
br.close(); // BufferedReader를 닫아 자원을 해제합니다.
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.