프로그래머스/코딩문제

[프로그래머스] Lv.0 코드 처리하기

쟌문 2023. 10. 20. 18:02
반응형

문제 바로가기

🔖 문제 설명 

문자열 code가 주어집니다. 

code를 앞에서부터 읽으면서 만약 문자가 "1"이면 mode를 바꿉니다. mode에 따라 code를 읽어가면서 문자열 ret을 만들어냅니다. 

mode는 0과 1이 있으며, idx를 0 부터 code의 길이 - 1 까지 1씩 키워나가면서 code[idx]의 값에 따라 다음과 같이 행동합니다. 

  • mode가 0일 때 
    • code[idx]가 "1"이 아니면 idx가 짝수일 때만 ret의 맨 뒤에 code[idx]를 추가합니다. 
    • code[idx]가 "1"이면 mode를 0에서 1로 바꿉니다. 
  • mode가 1일 때 
    • code[idx]가 "1"이 아니면 idx가 홀수일 때만 ret의 맨 뒤에 code[idx]를 추가합니다. 
    • code[idx]가 "1"이면 mode를 1에서 0으로 바꿉니다. 

문자열 code를 통해 만들어진 문자열 ret를 return 하는 solution 함수를 완성해 주세요.

 

단, 시작할 때 mode는 0이며, return 하려는 ret가 만약 빈 문자열이라면 대신 "EMPTY"를 return 합니다.

 

 


⛔ 제한사항

  • 1 ≤ code의 길이 ≤ 100,000 
    • code는 알파벳 소문자 또는 "1"로 이루어진 문자열입니다.

 


📋 입출력 예

code result
"abc1abc1abc" "acbac"

 

 


🔖 입출력 예 설명

입출력 예 #1

  • code의 각 인덱스 i에 따라 다음과 같이 mode와 ret가 변합니다.
code[i]  mode  ret
0 "a" 0 "a"
1 "b" 0 "a"
"c"  "ac"
3 "1" 1 "ac"
4 "a" 1 "ac"
5 "b" 1 "acb"
6 "c"  1 "acb"
7 "1" 0 "acb"
8 "a" 0 "acba"
9 "b" 0 "acba"
10 "c"  0 "acbac"

따라서 "acbac"를 return 합니다.

 

 


🧾 기본 제공 코드

function solution(code) {
    var answer = '';
    return answer;
}
 
 
 

🗳️ 직접 풀이한 코드

function solution(code) {
    const arr = code.split('');
    let mode = 0;
    let ret = '';
    
    for (const [idx, code] of arr.entries()) {
        if (mode === 0) {
            if (code !== '1') {
                if (idx % 2 === 0) {
                    ret += code;
                }
            } else {
                mode = 1;
            }
        } else {
            if (code !== '1') {
                if (idx % 2 !== 0) {
                    ret += code;
                }
            } else {
               mode = 0;
            }
        }
    }
    
    return ret.length ? ret : 'EMPTY';
}

먼저 문제 설명에서 제시한 대로 풀어봤다.

if문을 활용하여 조건에 충족되도록 순차적으로 풀었다.

다만 풀고 나서 아쉬운 마음이 들었다.

위 풀이로 코드가 정상 동작되는 것은 확인했지만

중첩된 if문들과 세로로 길어진 코드들로 인해 직관적이지 못했고 가독성이 떨어진다고 느껴져 아쉬웠다.

 

 


🗳️ 다른 사람이 풀이한 코드

function solution(code) {
    let answer = '';
    let mode = 0;

    for (let i = 0; i < code.length; i += 1) {
      if (Number(code[i]) === 1) {
        mode = mode === 1 ? 0 : 1;
      }
      if (Number(code[i]) !== 1 && i % 2 === mode) {
        answer += code[i];
      }
    }
    return answer.length > 0 ? answer : 'EMPTY';
}

다른 사람들이 풀이한 코드들 중 가장 많은 좋아요를 받은 풀이다.

확실히 직접 풀이한 코드와 많이 비교된다는게 느껴졌다.

다른걸 다 떠나서 가독성이 매우 뛰어나다는게 보였다.

 

위 코드는

answer에 문자가 추가되기 전 먼저 Number(code[i]) === 1mode를 체크하고

이후 mode의 상태값에 따라 answer 변수에 조건이 충족되는 문자가 추가되도록 하는

가독성도 좋고 몹시 직관적인 좋은 코드라는 생각이 들었다.

 

위 코드를 보고서 다시 풀어보고 싶었다.

그래서 직접 풀었던 코드를 한 번 엎었다.

참고로 봤던 위 코드를 머릿 속에 담아두고 코드를 이해해보기 위해 

직접 다시 풀어보면서 기억을 더듬으며 순차적으로 재차 풀어봤다.

 

 


🗳️ 다시 풀어본 코드

function solution(code) {
    let mode = 0;
    let ret = '';
    
    for (let idx = 0; idx < code.length; idx++) {
        if (code[idx] === '1') {
            mode = mode === 0 ? 1 : 0;
        }
        
        if (code[idx] !== '1') {
            if (mode === 0 && idx % 2 === 0) {     
                ret += code[idx];
            } 
            
            if (mode === 1 && idx % 2 === 1) {
                ret += code[idx];
            }
        }
    }
    
    return ret.length ? ret : 'EMPTY';
}

for... of 반복문 사용을 위해 생성했던 const arr = code.split(''); 배열을 삭제하고

효율성을 높이기 위해 간단한 for 반복문으로 수정했다.

그리고 과도하게 중첩됐던 if문을 줄이고 위와 같이 분류하여 구분지었다.

 

순탄하게 잘 작성해보던 중 막히는 부분이 있었다.

if (code[idx] !== '1') {
    if (mode === 0 && idx % 2 === 0) {     
        ret += code[idx];
    } 

    if (mode === 1 && idx % 2 === 1) {
        ret += code[idx];
    }
}

위 코드는 mode의 상태값에 따라 홀수번째 문자가 추가될지 짝수번째 문자가 추가될지

처리되는 코드다.

코드를 보면 알 수 있듯이 두 조건식의 구조가 매우 동일하다.

위 조건식의 구조가 동일한 건 알겠고 이를 어떻게 취합하면 좋을지 감이 오지 않았다.

 

한 번 비교해보면서 공통되는 부분을 찾아 취합하고 싶었다.

그래서 위 코드를 취합해보기 위해 두 조건식을 놓고 곰곰히 생각해봤다.

 

비교해보던 중 공통되면서도 유일하게 다른 부분을 찾을 수 있었다.

바로 mode의 비교값과 idx % 2 로 나누고 남는 값이 같다는 거였다.

그래서 이를 찾아내어 코드를 수정해 아래와 같이 수정할 수 있었다.

if (code[idx] !== '1' && idx % 2 === mode) {
    ret += code[idx];
}

 

 

🗳️ 최종 반영된 코드

function solution(code) {
    let mode = 0;
    let ret = '';
    
    for (let idx = 0; idx < code.length; idx++) {
        if (code[idx] === '1') {
            mode = mode === 0 ? 1 : 0;
        }
        
        if (code[idx] !== '1' && idx % 2 === mode) {
            ret += code[idx];
        }
    }
    
    return ret.length ? ret : 'EMPTY';
}

 

 


💬 마치며

다시 풀면서 느낀거지만 다시 풀어보길 잘했다는 생각이 들었다.

좋은 코드라고 생각했던 코드를 기준으로 기억을 더듬어가며 다시 풀어본거지만

직접 풀어보면서 코드를 이해할 수 있었고, 또 눈으로만 보고 지나쳤다면 간과했을 코드 구조를

직접 구현을 통해 왜 그렇게 코드가 구성되었는지를 인지하고 이해할 수 있는 시간이 됐던 거 같아 좋았다.

앞으로 다른 코드들을 짤 때도 내가 직접 짠 코드가 아쉽다면

왜 아쉬운지 그리고 그 아쉬움을 어떻게 해결할 수 있을지,

어떻게 리팩토링을 하면 더 효율적인 코드로 짤 수 있을지를 생각하면서 풀어봐야겠다는 다짐의 순간이었다.

 

 


🔸 작성된 본문 내용 중 미흡한 부분이 있을 수 있습니다.
🔸 고칠 부분이나 추가되면 좋을 내용 댓글로 남겨주시면 완성도 높은 글을 만들어가는 데에 큰 힘이 됩니다. ☺️

 

반응형