코드 분석_백준 12891 (Java)

Kwon Donghyun·2024년 2월 15일
0

백준 12891 DNA 비밀번호 문제를 풀고 다른 사람의 코드를 보며 이해가 안 되었던 코드가 있어 코드를 분석해보고 정리하는 글 입니다.

백준 - 문제

유저 : sa5369 & 코드

코드는 해당 문제를 풀어야지 보실 수 있습니다.


// 코드 일부

public class P12891_sa5369_62956445 {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    static int dnaStrLen, subStrLen;
    static int[] dnaStr;
    static int[] acgt;

    public static void main(String[] args) throws Exception {
        dnaStrLen = read();
        subStrLen = read();
    }

    public static int read() throws Exception {
        int c, n = System.in.read() & 15;
        while ((c = System.in.read()) > 32)
            n = (n << 3) + (n << 1) + (c & 15);

        return n;
    }
}

위 코드에서 read() 메서드 부분이었다.

입력 처리를 보통 BufferedReader & StringTokenizer를 통해 처리하는데 위 코드는 특이하게 System.in.read()를 사용했다.

StringTokenizer

문자열을 구분자를 이용해 분리할 때 사용할 수 있다.
BufferReader를 통해 라인 단위로 읽어들이는데 StringTokenizer를 통해 문자열을 여러 개의 토큰으로 분리한다.

System.in.read()

자바는 기본적으로 아스키 코드 값이 입력된다.
한 글자씩 입력받아 해당 값의 아스키 코드 값을 반환한다.

(아스키 코드 일부)
\n : 10, 공백 : 32, 0 : 48, 9 : 57, A : 65, Z : 90, a : 97, z : 122

int c, n = System.in.read() & 15;

  • c는 초기화되지 않았다.
  • n은 & 15를 통해 아스키 코드 값을 입력 받고 하위 4비트만 가져온다.
    • 뒤에 4자리만 가져오면 숫자의 경우 0 ~ 9의 값을 가져오게 된다.
    • ex) 2 -> 50 (110010) & 15 => 2(0010)로 반환된다.

while((c = System.in.read()) > 32)

  • c에 다음 입력을 확인해서 32보다 클 경우 반복문을 실행한다.
    • 32는 공백이다.
  • 연속된 문자를 확인할 수 있다.
    • ex) 10 입력 시 c = 48이다.

n = (n << 3) + (n << 1) + (c & 15)

  • (n << 3) + (n << 1)는 기존 숫자를 * 10 하는 것과 같은 결과이다.
    • << >>는 비트 쉬프트 연산자이다.
  • n << 3 : n * 8 (2^3)이고, n << 1 : n * 2 (2^1)
    • 1 => 1 * 8 + 1 * 2 => 8 + 2 => 10이 된다.
    • 5 => 5 * 8 + 5 * 2 => 40 + 10 => 50이 된다.
    • 9 => 9 * 8 + 9 * 2 => 72 + 18 => 90이 된다.
  • 기존 숫자에 10을 곱한 뒤 다음 문자열 c에서 하위 4비트만 가져와 숫자를 더하게 된다.
    • 10 입력 시 1에서 10을 곱한 10에 48의 하위 4비트 0을 더해 10을 반환한다.
    • 92 입력 시 9에서 10을 곱한 90에 50의 하위 4비트 2를 더해 92를 반환한다.

정리

  • 내 코드의 경우 302 ms가 소요되고, 해당 코드는 208 ms가 소요된다.
  • 입력에 대한 처리를 오직 Scanner와 BufferedReader & StringTokenizer로만 가능한 것처럼 사용했었는데 아스키 코드와 쉬프트 연산을 통해 처리할 수 있는 방법을 알게 되었다.
  • 기본적인 개념들은 알고 있었지만, 해당 코드를 보자마자 이해되지 않는 것을 느끼고 어떤 부분이 부족하고 까먹었는지 알게 되어 다시 한번 해당 개념을 학습하고 이해할 수 있어 좋았다.

0개의 댓글