본문 바로가기
PS/BOJ

[자바] 백준 2999 - 비밀 이메일 (java)

by Nahwasa 2023. 1. 27.

 문제 : boj2999


 

필요 알고리즘 개념

  • 구현, 문자열
    • 문자열을 파싱해서 문제에서 제시된대로 구현해주는 문제이다.

※ 제 코드에서 왜 main 함수에 로직을 직접 작성하지 않았는지, 왜 Scanner를 쓰지 않고 BufferedReader를 사용했는지 등에 대해서는 '자바로 백준 풀 때의 팁 및 주의점' 글을 참고해주세요. 백준을 자바로 풀어보려고 시작하시는 분이나, 백준에서 자바로 풀 때의 팁을 원하시는 분들도 보시는걸 추천드립니다.

 


 

풀이

1. 우선 R과 C를 구해야 한다.

  R<=C이고, R과 C는 둘 다 자연수여야 하며, 이러한 경우가 여럿일 경우 R이 큰 값을 선택해야 한다. 따라서 입력받은 문자열의 길이를 L이라 할 때, sqrt(L) 부터 1까지 확인하며 L이 나누어떨어지는 값을 찾자. 그게 R값이다. 왜 sqrt(L) 부터 확인하면 되는지는 '에라토스테네스의 체 혹은 소수판정 시 제곱근 까지만 확인하면 되는 이유' 글을 보면 알 수 있다. 혹은 어차피 L의 최대치가 100이므로 그냥 찾아도 되긴 하다.

 public String solution(String msg) throws Exception {
    int r = getR(msg.length());
    int c = msg.length()/r;
	...
}

private int getR(int len) {
    for (int i = (int) Math.sqrt(len); i >= 1; i--)
        if (len%i==0) return i;	// 나누어 떨어지는걸 찾을 시 i 리턴
    return 0;
}

 

2. 이제 세로로 써져있던걸 가로로 출력해줘야 한다.

  R과 C를 구했으니 출력은 어렵지 않다. 초기 문자열에서 세로순서를 가로 순서로 바꿔주면 되므로, 아래처럼 출력해주면 된다.

public String solution(String msg) throws Exception {
    int r = getR(msg.length());
    int c = msg.length()/r;

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < r; i++) {
        for (int j = 0; j < c; j++) {
            sb.append(msg.charAt(j*r+i));
        }
    }
    return sb.toString();
}

 

  바로 수식으로 위치 찾는 것이 잘 이해가 안된다면 char[R][C] 배열에 기존 문자열을 세로로 넣은 후, 가로로 다시 출력해주는 식으로도 가능하다.

 


 

코드 : github

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

public class Main {
    private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in), 1<<16);

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        System.out.println(main.solution(br.readLine()));
    }

    public String solution(String msg) throws Exception {
        int r = getR(msg.length());
        int c = msg.length()/r;

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                sb.append(msg.charAt(j*r+i));
            }
        }
        return sb.toString();
    }

    private int getR(int len) {
        for (int i = (int) Math.sqrt(len); i >= 1; i--)
            if (len%i==0) return i;
        return 0;
    }
}

댓글