Algorithm/푼 문제

프로그래머스/Lv0/숨어있는 숫자의 덧셈 (2)

안개바다 2023. 4. 2. 00:13

문제 설명

문자열 my_string이 매개변수로 주어집니다. my_string은 소문자, 대문자, 자연수로만 구성되어있습니다. my_string안의 자연수들의 합을 return하도록 solution 함수를 완성해주세요.

제한사항

  • 1 ≤ my_string의 길이 ≤ 1,000
  • 1 ≤ my_string 안의 자연수 ≤ 1000
  • 연속된 수는 하나의 숫자로 간주합니다.
  • 000123과 같이 0이 선행하는 경우는 없습니다.
  • 문자열에 자연수가 없는 경우 0을 return 해주세요.

입출력 예

my_string result
"aAb1B2cC34oOp" 37
"1a2b3c4d123Z" 133

 


처음에는 단순하게 정규표현식을 사용해서 영어만 filter 메소드를 통해 제거하고 reduce메소드를 통해 합을 return 할 생각을 했지만

34같은 2자리 이상 숫자들이 함정 처럼 숨어있어서 이 방법을 포기하고

Stack을 이용한 풀이 방식을 적용해봤다.

Lv0 문제이니 만큼 논리는 단순한다.

1) stack = '' ; 을 선언하고

2) my_string을 순회해서 처음 숫자가 나오면  stack에 그 숫자가 끝날때까지 계속 더하는 것이다.

3) 그러다 숫자가 끝나고 알파벳이 오면 지금까지의 stack을 빈 배열 numArr에 push하고

4) stack을 다시 ''로 선언한다. 

 그렇게 해서 나오게 된 코드는


function solution(my_string) {
    let stack = '';
    let numArr = [];
    
    for(const el of my_string){
        if(el.match(/[0-9]/g)){
            stack+=el
        }else{
            stack === '' ? '': numArr.push(stack) 
            stack =''
        }
    };
    if(stack !== '') numArr.push(stack);
    
    return numArr.reduce((acc,index)=>acc+Number(index),0);
}

이후에 정규표현식을 복습하고 풀이의 방향을 바꿔 보았다.

모든 알파벳을 공백(" ")으로 대체하고 공백을 기준으로 split 메소드를 적용하면 깔끔하게 숫자들만 분리가 된다. 이후 이 숫자들만 reduce 해주면 된다.

그렇게 해서 나온 코드는


function solution(my_string) {
    return my_string.replace(/[A-z]/g, " ").split(" ").reduce((acc,index) => acc+Number(index),0)
}

단, 숫자들은 아직 string으로 되어 있기때문에 Number() 메소드를 적용해서 숫자로 변환 후 합 했다. 

map 메소드를 적용해 미리 숫자로 변경해도 된다.


다른 분들의 풀이 중 정규표현식을 적용한 풀이를 소개한다.

function solution(my_string) { 
  return my_string.split(/\D+/).reduce((acc, cur) => acc + Number(cur), 0);
}

/\D+/ 라는 표현식을 사용해 본적이 없는데, 직접 사용해 보니 첫번째 예시 "aAb1B2cC34oOp"에 my_string.split(/\D+/) 을 적용하면

["", "1", "2", "34", ""] 이런 결과를 반환한다. 숫자만을 정확하게 분리한다.

Number("")은 0으로 계산되기에 위와 동일한 방식으로 reduce 메소드를 적용하면 된다.

 

만약 이 문제를 정규표현식 없이 풀었다면, 꼭 정규표현식으로 다시 풀어보기를 추천한다. 코드가 간결해지고 이해하기 쉬워지고 빨라진다.