<1.12> 암호

mutexlocking·2022년 7월 12일
0

문제
: 4 , #**###############** 와 같이 변환할 문자의 개수와 암호를 보내면, 총 암호를 7글자씩 바라보고 , #을 1로 별문자를 0으로 변환했을 때 나오는 이진수를, 다시 십진수로 변환하여 , 그 아스키코드로 된 문자열을 출력하라.

이 문제는 문제 자체는 길었지만,
결국 요구하는 바는 단순하고 그에 따라 해결책도 직관적으로 생각할 수 있는 문제였다.

[요구사항]
1. 총 암호에 대해서 7글자씩 잘랐을 때
2. 7글자씩 자른 암호를 이진수로 변환하고
3. 각 이진수를 십진수로 변환하여
4. 그 십진수의 아스키코드값을 갖는 문자로 변환하라

[요구사항에 따른 해결책]
1. StringBuilder() 클래스의 인스턴스 메서드 , subString()을 사용하여 7글자씩 문자열을 자를 수 있다.
2. 문제에서 주어진 대로 "샵문자"는 1로 , '별문자'는 0으로 변환하여 이진수를 만들고
3. 각 자리수가 2의 제곱수라는 점을 이용하여, 이진수를 십진수로 변환한 후
4. 그 십진수가 int형 값으로 나올텐데, 이를 char 형으로 강제 형변환 하여 , 그 아스키코드 값을 갖는 문자로 변환

위 해결 로직을 기반으로 아래와 같은 코드를 작성하였다.

import java.util.Scanner;

public class Main {

    /** 이진수로 된 int배열을 받아 -> 십진수로 변환해 주는 메서드 */
    public static int convertDecimal(int[] binary){
        int tmp = 1;
        int result = 0;
        for(int i = binary.length-1; i>=0; i--){
            result += (binary[i] * tmp);
            tmp *= 2;
        }

        return result;
    }

    public static String solution(String str, int num){

        String result = "";
        String[] strArr = new String[num];
        int[] binaryArr = new int[7];

        //1. 7개의 문자 단위로 문자열을 자름
        for(int i=0, j=0; i<num; i++, j+=7){
            strArr[i] = new StringBuilder(str).substring(j, j + 7).toString();
        }

        //2. 잘라진 문자열별로 이진수로 변환 후 -> 변환한 이진수를 바로 아스시코드(십진수)로 변환 -> 후 바로 문자로 변환하여 누적
        for (String s : strArr) {
            char[] charArr = s.toCharArray();
            for(int i=0; i<7; i++){
                binaryArr[i] = charArr[i]=='#' ? 1 : 0;
            }
            char c = (char)convertDecimal(binaryArr);
            result += c;
        }

        return result;
    }

    public static void main(String[] args) {

        //0. Scanner 준비
        Scanner sc = new Scanner(System.in);

        //1. 문자의 개수와 , 총문자열 입력
        int num = sc.nextInt();
        String str = sc.next();

        //2. solution()을 호출하면서 입력받은 문자의 개수와 총문자열을 인자로 넘김
        String result = solution(str, num);

        //3. 반환받은 결과 출력
        System.out.println(result);
    }
}

이렇게 간단한 문제를 직관적으로 잘 해결했다고 생각하고 선생님강의를 들었는데,
샵문자와 별문자를 1과 0으로 변환하는 로직과 ,
이진수문자열을 10진수값으로 변환하는 로직이
이미 메서드로 제공되고 있다는 점에 놀랐다.

문자 변환 메서드는 지난 문제에서 사용한 StringBuilder의 replace() 메서드 이고,
이진수 문자열을 십진수 값으로 변환해주는 메서드는 Integer.parseInt(str,2) 였다.

제공되는걸 쓰냐 or 나이브하게 다 구현하냐 의 차이긴 하지만,
제한된 시간안에 문제를 해결하고 , 더 가독성 좋은 코드를 위해서는
제공되는 메서드를 잘 알고 - 적재적소에 사용할 줄 아는 능력도 필요
하다고 생각이 들었다.

따라서 위 두 메서드를 통해 다시한번 코드를 작성해 보았다.

import java.util.Scanner;

public class Main2 {

    public static String solution(String str, int num){
        String result = "";

        for(int i = 0, j = 0; i<num ; i++ , j+=7){
            String tmp = new StringBuilder(str).substring(j, j+7)
                    .replace('#','1')
                    .replace('*','0')
                    .toString();

            result += (char)(Integer.parseInt(tmp,2));
        }

        return result;
    }

    public static void main(String[] args) {
        //0. Scanner 준비
        Scanner sc = new Scanner(System.in);

        //1. 문자의 개수와 , 총문자열 입력
        int num = sc.nextInt();
        String str = sc.next();

        //2. solution()을 호출하면서 입력받은 문자의 개수와 총문자열을 인자로 넘김
        String result = solution(str, num);

        //3. 반환받은 결과 출력
        System.out.println(result);
    }
}

[이를 통해 알게된 점]

  • StringBuilder 클래스의 subString() 메서드를 이용하여 , (파이썬과 같이) 문자열을 index 단위로 자를 수 있다.
    • 이때 subString(0, 7) 로 호출하면, 0번 인덱스 부터 (7-1)번 인덱스까지 만 을 자른다는점을 주의해야 한다.
  • 자바에서는 아스키코드값을 문자로 어떻게 변환하는지 확실히 알지 못했는데, 이번 경험을 통해 int값을 char형으로 강제 형변환 하면
    그 int형 값 아스키 코드에 따른 문자로 변환된다는 사실을 알게 되었다.
  • StringBuilder 클래스의 replace()를 이용하여 문자를 다른 문자로 쉽게 변환할 수 있다
    • 심지어 이를 chain형식으로 이어 사용 하여 ,
      여러 문자를 모두 변환시킬 수 도 있다.
  • Integer.parseInt()를 사용하여 숫자로된 특정 문자열을 Integer값으로 변환할 수 있는데, 이때 두번째 인자로 radix 값을 지정함에 따라
    [2진수를 -> 10진수로] 변환
    할 수도 있다.
profile
개발자가 되고자 try 하는중

0개의 댓글