백준 홍익 댄스파티

KIMYEONGJUN·2026년 1월 16일
post-thumbnail

문제

내가 생각했을때 문제에서 원하는부분

댄스파티의 사진이 5줄의 문자열로 주어진다.
각 줄의 최대 길이는 10000자이며 모든 줄의 길이는 동일하다.
각 열은 도약 준비, 도약 중, 착석 중 하나이다.

입력으로 주어진 댄스파티 사진의 다음 차례의 모습을 5줄의 문자열로 출력한다.

내가 이 문제를 보고 생각해본 부분

입력 처리 준비 (BufferedReader 및 배열 초기화)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.in은 표준 입력 스트림(일반적으로 키보드 입력)이다. 
이 입력은 기본적으로 바이트 단위로 들어오기 때문에 문자 단위로 처리하기 위해서는 InputStreamReader를 사용하여 바이트 스트림을 문자 스트림으로 변환해준다.
BufferedReader는 문자 스트림으로부터 텍스트를 효율적으로 읽기 위한 래퍼(wrapper) 클래스이다. 
큰 버퍼를 사용하여 한 번에 많은 데이터를 읽어오기 때문에, 특히 많은 양의 줄(line) 단위 입력을 처리할 때 Scanner보다 빠르고 효율적이다. 
throws IOException은 입출력 과정에서 발생할 수 있는 오류를 main 메서드에서 처리하겠다는 의미이다.
String[] partyPeople = new String[5];
댄스파티 사진은 총 5줄로 주어지므로, 이 5줄의 문자열을 저장할 String 타입의 배열 partyPeople을 선언하고 크기를 5로 지정한다.
for (int j = 0; j < 5; j++) { partyPeople[j] = br.readLine(); }
for 반복문을 사용하여 총 5번 반복하면서 br.readLine()을 통해 한 줄씩 입력을 읽어 partyPeople 배열의 각 인덱스에 저장한다. 
이제 partyPeople[0]에는 첫 번째 줄, partyPeople[1]에는 두 번째 줄 ... 과 같이 사진의 현재 모습이 저장된다.
결과를 저장할 StringBuilder 배열 초기화
StringBuilder[] photo = new StringBuilder[5];
다음 차례의 댄스파티 사진, 즉 최종 결과 또한 5줄의 문자열로 나타나야 한다.
String 객체는 한 번 생성되면 내용을 변경할 수 없어서, 문자열을 계속 덧붙이는 작업(append)을 하면 메모리 낭비와 성능 저하가 발생할 수 있다.
이를 해결하기 위해 StringBuilder를 사용하는데, StringBuilder는 가변적인 문자열을 효율적으로 다룰 수 있게 해준다. 
photo 배열은 이 StringBuilder 객체 5개를 담을 공간이다.
for (int j = 0; j < 5; j++) { photo[j] = new StringBuilder(); }
photo 배열의 각 요소에 실제 StringBuilder 객체를 생성하여 할당한다. 
이제 photo[0]은 출력될 첫 번째 줄을, photo[1]은 두 번째 줄을 만드는 역할을 하게 된다.
사진의 열 개수 파악
int numCols = partyPeople[0] != null ? partyPeople[0].length() : 0;
문제에서 모든 줄의 길이는 동일하다고 했으므로, 첫 번째 줄(partyPeople[0])의 길이만 알면 전체 사진의 열(가로) 개수를 알 수 있다. 
partyPeople[0].length()를 통해 이를 가져온다.
partyPeople[0] != null ? ... : 0 부분은 혹시 모를 NullPointerException을 방지하기 위한 안전 코드이다. 
첫 번째 줄이 null이 아닐 경우에만 길이를 가져오고, 그렇지 않으면 0을 반환한다.
각 열(Column)의 상태 변화 계산
for (int i = 0; i < numCols; i++) { ... }
i는 현재 처리할 "열 인덱스"를 의미한다. 
numCols만큼 반복하며 사진의 모든 열을 왼쪽에서 오른쪽으로 하나씩 처리한다.
peopleMod 생성 (현재 열의 세로 문자열)
StringBuilder peopleModBuilder = new StringBuilder();
현재 열에 해당하는 5개의 문자를 세로로 모아 하나의 String으로 만들기 위해 임시 StringBuilder를 선언한다.
for (int j = 0; j < 5; j++) { peopleModBuilder.append(partyPeople[j].charAt(i)); }
내부 for 반복문은 j를 0부터 4까지(즉, 5개의 행) 순회하면서 각 행(partyPeople[j])에서 현재 열 i에 해당하는 문자(charAt(i))를 가져와 peopleModBuilder에 덧붙인다.
예를 들어, 첫 번째 열(i = 0)의 경우 partyPeople[0].charAt(0), partyPeople[1].charAt(0), ..., partyPeople[4].charAt(0)을 모아서 하나의 문자열을 만든다.
String peopleMod = peopleModBuilder.toString();
peopleModBuilder에 저장된 5개 문자의 세로 문자열을 String 타입으로 변환하여 peopleMod 변수에 저장한다. 
이 peopleMod가 바로 현재 열의 "상태"를 나타낸다.
if-else if-else 조건문을 통한 상태 변화 판별
if (peopleMod.equals(".omln")) { ... }
peopleMod가 .omln과 같으면, 이는 현재 열의 학생들이 모두 "도약 준비" 상태임을 의미한다. (문제에서 주어진 표의 '도약 준비' 열의 문자들을 세로로 읽으면 .omln이 된다.)
이 경우, 다음 차례에는 모든 학생이 "도약 중" 상태로 바뀐다. 
해당되는 문자들(o, w, l, n, .)을 photo 배열의 각 줄 StringBuilder에 append하여 다음 사진의 모습을 만든다.
else if (peopleMod.equals("owln.")) { ... }
peopleMod가 owln.과 같으면, 현재 열의 학생들이 모두 "도약 중" 상태임을 의미한다. (문제에서 주어진 표의 '도약 중' 열의 문자들을 세로로 읽으면 owln.이 된다.)
이 경우, 다음 차례에는 모든 학생이 "도약 준비" 상태로 바뀐다. 
해당되는 문자들(., o, m, l, n)을 photo 배열의 각 줄 StringBuilder에 append한다.
else { ... }
앞의 두 경우가 아니라면, 현재 열의 학생들은 "착석" 상태임을 의미한다. (문제에서 주어진 표의 '착석' 열의 문자들을 세로로 읽으면 .oLn이 되는데, else 조건으로 이 상태를 커버한다.)
"착석" 상태의 학생들은 다음 차례에도 변하지 않으므로, 원래 "착석" 상태를 나타내는 문자들(., ., o, L, n)을 photo 배열의 각 줄 StringBuilder에 append한다.
최종 결과 출력
for (StringBuilder p : photo) { System.out.println(p.toString()); }
모든 열에 대한 처리가 끝나면 photo 배열의 각 StringBuilder에는 다음 차례의 사진 각 줄이 완성되어 있다.
향상된 for문을 사용하여 photo 배열의 각 StringBuilder p에 접근하고, p.toString()으로 StringBuilder 객체를 String으로 변환한 후 System.out.println()으로 출력한다. 
println은 자동으로 줄바꿈을 포함한다.
br.close();
BufferedReader를 사용한 후에는 자원 누수를 방지하기 위해 반드시 close() 메소드를 호출하여 닫아주어야 한다.

코드로 구현

package baekjoon.baekjoon_32;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

// 백준 23321번 문제
public class Main1269 {
    public static void main(String[] args) throws IOException { // 입출력 예외 처리
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // 댄스파티 사진 (5줄)을 저장할 배열
        String[] partyPeople = new String[5];
        for (int j = 0; j < 5; j++) {
            partyPeople[j] = br.readLine(); // 각 줄을 읽어 배열에 저장
        }

        // 다음 차례의 댄스파티 사진을 만들기 위한 StringBuilder 배열 초기화
        StringBuilder[] photo = new StringBuilder[5];
        for (int j = 0; j < 5; j++) {
            photo[j] = new StringBuilder(); // 각 줄에 대한 StringBuilder 생성
        }

        // 입력의 첫 번째 줄 길이를 기준으로 전체 열 개수 파악
        int numCols = partyPeople[0] != null ? partyPeople[0].length() : 0;

        // 각 열(column)을 순회하며 다음 상태를 결정
        for (int i = 0; i < numCols; i++) {
            // 현재 열의 5개 문자를 세로로 모아 하나의 문자열(peopleMod) 생성
            StringBuilder peopleModBuilder = new StringBuilder();
            for (int j = 0; j < 5; j++) {
                peopleModBuilder.append(partyPeople[j].charAt(i));
            }
            String peopleMod = peopleModBuilder.toString();

            // peopleMod(현재 열의 상태)에 따라 다음 열의 상태를 photo에 추가
            if (peopleMod.equals(".omln")) { // 현재 열이 '도약 준비' 상태일 때
                photo[0].append('o'); // 도약 중으로 변경 (1행)
                photo[1].append('w'); // 도약 중으로 변경 (2행)
                photo[2].append('l'); // 도약 중으로 변경 (3행)
                photo[3].append('n'); // 도약 중으로 변경 (4행)
                photo[4].append('.'); // 도약 중으로 변경 (5행)
            } else if (peopleMod.equals("owln.")) { // 현재 열이 '도약 중' 상태일 때
                photo[0].append('.'); // 도약 준비로 변경 (1행)
                photo[1].append('o'); // 도약 준비로 변경 (2행)
                photo[2].append('m'); // 도약 준비로 변경 (3행)
                photo[3].append('l'); // 도약 준비로 변경 (4행)
                photo[4].append('n'); // 도약 준비로 변경 (5행)
            } else { // 현재 열이 '착석' 상태일 때 (나머지 경우)
                photo[0].append('.'); // 착석 상태 유지 (1행)
                photo[1].append('.'); // 착석 상태 유지 (2행)
                photo[2].append('o'); // 착석 상태 유지 (3행)
                photo[3].append('L'); // 착석 상태 유지 (4행)
                photo[4].append('n'); // 착석 상태 유지 (5행)
            }
        }

        // 최종 결과(다음 차례 사진) 출력
        for (StringBuilder p : photo) {
            System.out.println(p.toString()); // 각 줄 출력
        }

        br.close(); // BufferedReader 리소스 해제
    }
}

마무리

코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.

profile
Junior backend developer

0개의 댓글