Bin's Blog

[프로그래머스] Level2 - 압축(Javascript) 본문

Algorithm

[프로그래머스] Level2 - 압축(Javascript)

hotIce 2023. 4. 22. 23:05
728x90
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

▶ 문제 요약

1. 주어진 영문 대문자로만 이루어진 문자열을 압축하고, 압축한 결과를 사전 색인 번호의 배열로 출력

2. 주어진 입력 문자열을 LZW 압축 알고리즘에 따라 처리하고, 압축 과정에서 발생하는 사전의 업데이트와 출력을 기록한다.

3. 압축한 후의 사전 색인 번호를 배열로 출력해야 한다. 

 

▶ 코드

function solution(msg) {
    let answer = [];
    //map 활용
    const map = new Map();
    
    // a-z까지 숫자랑 함께 Map()에 담기
    for (let i = 0; i < 26; i++) {
        const letter = String.fromCharCode(65+i);
        // 문제에서 색인 번호는 1번부터 시작
        const number = i + 1;
        // a-z와 그에 해당하는 숫자를 같이 map에 넣기
        map.set(letter, number);
    }
    
    // 문자열을 담기 위해서 초기에 변수를 저장
    let alpha = "";
    // 주어진 입력값을 돌면서
    for (let j = 0; j < msg.length; j++) {
        // 입력값 더해주기
        alpha += msg[j];
        // 만약에 현재 누적된 문자열이 map에 없으면
        if (map.get(alpha) === undefined) {
            // map에 새로 추가하고 새로운 번호를 부여
            map.set(alpha, map.size +1);
            // 문자열의 길이가 1이 아닌 2인 경우를 점검
            if (alpha.length > 1) {
            	// 새로운 문자가 들어오면 이전까지의 문자를 담기
                answer.push(map.get(alpha.slice(0, -1)));
                // 다음에 새로운 문자부터 다시 출발
                j--;
            }
            // 기존에 담긴 문자열 초기화
            alpha = "";
        }
    }
    // 만약에 처리되지 않은 글자가 있다면 해당 글자의 번호를 배열에 넣기
    if (alpha) {
        answer.push(map.get(alpha));
    }
    return answer;
}

▶ 풀이 과정

1.  먼저 Map()함수를 활용해서 [A-Z]까지 담아줬다. String.fromCharCode() 메서드를 활용했다. 주어진 유니코드(국제 문자 코드 표준) 값에 해당하는 문자열을 생성해서 반환한다. 알파벳 "A"의 유니코드 값은 65이다. 알파벳은 총 26개니까 for문을 돌면서 유니코드 값에 + i를 해주면 [A-Z]까지 차례대로 담긴다. 인덱스의 특성상 0부터 시작이다보니 주어진 문제에서 색인 번호의 시작 번호는 1번이다. 그렇기 때문에 i에 1을 더해주고 map에 알파벳과 해당 번호를 넣어줬다.

 

2.  해당 문자열을 압축하기 위해서 입력 문자열을 받기 위해서 변수를 만들어주고 for문을 돌면서 입력값을 더해주면서 해당 단어가 기존에 map에 있는지 없는지를 체크한다. 여기서 "map.get(alpha) === undefined" 이 부분에 대해서 말하자면 get() 메서드를 통해서 해당 문자열이 없으면 "undefined"를 출력한다. 새로운 사전 단어의 경우가 이에 해당한다. 새로운 단어의 경우에는 map에 단어와 새로 번호를 부여하는데... 이때 새로운 번호는 사전에서 가장 끝 번호이기 때문에 map.size() 메서드를 활용해서 담아준다.

 

3.  지금 단어의 길이가 1이라면 이미 map에 [A-Z]가 담겨져 있으니 볼 필요가 없고 길이가 2인 단어부터 본다. 새로운 단어가 들어오면 이전 단어의 번호를 배열에 담아서 출력해야 한다.

EX) 예를 들어 문제에서 예제 1번을 보면 KAKAO를 보자 "K"는 map에서 11번에 해당한다. 그러다가 "A"가 새로 들어와서 "KA"가 된다면  사전에 없는 단어가 된다. 그러면 27번을 사전에 추가하고 출력은 "A"가 들어오기 전에 K에 해당하는 번호이다. 

현재 문자열을 slice()메서드를 활용해서 (0, -1)의 의미는 시작점은 0이고 종료 시점은 -1인데 -1은 문자에서 마지막 새롭게 들어오는 글자에 해당한다. 마지막 새로운 글자만 제외한 부분을 추출해서 해당 단어를 map에서 찾아서 배열에 담아준다.

이전 마지막 글자부터 다시 탐색을 시작하기 위해서 j에 -1을 했고 새로운 단어를 담기 위해서 이전에 담았던 문자를 초기화해줬다.

 

4.  문제에서 요구하는대로 마지막으로 처리되지 않은 글자가 존재한다. "if (alpha)"라고 하면 alpha에 어떠한 값이 존재하는지를 묻는다. 만약에 있다면 단어에 해당하는 값을 배열에 담아주고 최종적으로 배열을 호출하면 된다. 

 

▶ 배운점

1. Map()함수를 활용하면 빠르게 알파벳 사전을 만들 수 있고 값을 확인하고 새로 삽입하는 과정이 효율적이고 편하다. 자주 애용하자.

2. 유니코드를 활용해서 알파벳을 담는 법을 배웠다.

728x90