한 걸음씩

[프로그래머스][JS] 컨트롤 제트 본문

Programmers

[프로그래머스][JS] 컨트롤 제트

winter17 2023. 6. 10. 19:13

https://school.programmers.co.kr/learn/courses/30/lessons/120853

 

프로그래머스

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

programmers.co.kr

풀이 과정

function solution(s) {
    const array = s.split(' ') // 공백으로 구분하여 배열 변환

    const arrNum = array.map(item => { // 정수와 'Z'조합으로 배열 생성
        const num = parseInt(item)
        return isNaN(num) ? item : num
    })

    // 'Z'의 인덱스를 찾아서 바로 앞의 값들의 합을 구하기
    let cnt = 0
    for (let i = 0; i < arrNum.length; i++){
        if (arrNum[i] === 'Z'){
            cnt += arrNum[i-1]
        }
    }   
    
    if (!arrNum.includes('Z')){ // 'Z'가 없다면 바로 합을 구하고
        const sum = arrNum.reduce((acc, cur) => acc + cur)
        return sum
    }else{ // 'Z'가 있다면 전체 합에서 cnt 빼기
        const sumNum = arrNum.filter(item => typeof item === 'number').reduce((acc, cur) => acc + cur)
        return sumNum - cnt
    }
}

테스트 통과는 했지만, 코드가 중복되는 부분들도 많고 가독성이 좀 떨어지는 것 같다.

 

마지막에 sumNum 변수에서 arrNum을 필터링할 때, item => parseInt(item) 이런 식으로 필터링을 해서 하나의 테스트 케이스가 통과가 안 됐는데 콘솔로 보면 제대로 나오고 있어서 어느 부분이 틀린 건지 몰라서 한참 헤맸다.

알고 보니까 parseInt(item)으로 필터링하면 정수가 아닌 경우는 단순히 NaN처리를 하는데 이때, reduce메서드로 더해버리면 오류가 나버릴 수 있다는 것이다. 

때문에, item 타입을 확인해서 'number'인 경우만 필터링해 reduce 메서드로 합을 구하는 게 더 맞는 코드인 것이다.

 

const sumNum = arrNum.filter(item => !isNaN(item));

위와 같은 결과를 가지는데 isNaN을 사용하는 것이 더 간단하고 직관적인 방법이다.


리뷰

다른 사람들 풀이를 보니까 스택처럼 접근하면 금방 풀리는 문제인데 나는 무작정 구현하려고해서 좀 복잡해진 것 같다.

function solution(s) {
    const stack = []

    s.split(' ').forEach((target) => { // 공백으로 구분하여 forEach로 배열 탐색
        if(target === 'Z') stack.pop(); // target이 'Z'라면 빈 stack 배열에서 삭제
        else stack.push(+target) 아니라면 target을 push
    })

    return stack.length ? stack.reduce((pre, cur) => pre + cur) : 0;
    // stack의 배열이 0이 아니라면, stack의 합을 구하기
}

s = "10 Z 20 Z 1"인 경우에 

10이 나오면 빈 배열에 push했다가 Z가 나오면 10이 들어간 배열에 pop을 해서 꺼내는데

결국 10을 넣었다가 다시 뺀거니까 결과는 10 - 10 = 0