ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 프로그래머스 JS | 0단계 : 369게임
    문제풀이 2022. 12. 14. 15:54

     

     

     

     

    오늘도 어김없이 코딩 테스트 공부를 하던 와중... 한 문제의 '다른 사람 풀이'를 보고 지금 잡아놔야 한다는 생각에 글로 남긴다.

    0단계에 369게임이라는 문제.

    order에 할당된 숫자를 보고 3 or 6 or 9일 경우 박수를 치고, "총 몇 번 박수를 쳤는가"를 return 하라는 문제이다.

     

     


     

     

    나의 풀이 ~생각의 흐름~

    1. order 숫자를 하나하나 각각 따로 확인할 수 있어야 한다. (=> 배열로 바꿔야 한다!)

    2. 배열로 바꾸기 위해서는 string type 으로 바꿔야 한다. 

    3. "29423" 이렇게 바뀐 상태이므로 split()을 사용해서 각각 떨어뜨려 준다.

    4. 완성된 배열에 map()을 사용해서 string을 정수로 바꿔준다.

    5. 반복문을 사용해 3 혹은 6 혹은 9일 경우 answer의 값을 1씩 올린다.

    => 완성! 풀이완료!

    function solution(order) {
        let answer = 0;
        
        const arr = order.toString().split("").map((item) => parseInt(item));
        for(let i = 0; i < arr.length; i++) {
            if (arr[i] === 3 | arr[i] === 6 | arr[i] === 9) {
                answer++;
            }
        }
        return answer;
    }

     

    뿌듯하게 나름 완성을 하고, 참고 + 공부를 위해 다른 사람 풀이를 확인했다.

     

    다른 사람 풀이

    function solution(order) {
        var answer = [...order.toString().matchAll(/[3|6|9]/g)].length;
        return answer;
    }

     

    쿠궁...

    이렇게도 풀 수 있다니 ...... 멋지다!!

     

    나는 쪼갠 배열로 만들어서 for 반복문을 통해 하나씩 찾아 ++하는 방식으로 접근했으나

    이 풀이에서는 여러 메서드들(?)을 통해 조건에 맞는 요소들만 남긴 배열을 만들어 배열 안 요소들은 총 몇 개(박수 총 몇 번?)?라는 방식으로 접근했다.

     

    무의식적으로 뭐든 반복문으로 풀려고 하는데 여러 메서드들을 공부하고, 찾아보고, 응용해보려는 시도가 필요하다는 걸 느꼈다. 

    이 문제는 며칠 전에 푼 문제로 지금은 for 반복문 보다는 메서드들을 사용해서 해결하려고 노력하고 있다!

     

    그럼 ! 쪼개가며 알아보도록 하자.

     

    이 풀이법은 3,6,9만 남긴 배열을 만들고 배열의 length 속성을 이용해 바로 답을 찾아내는 방식이다.

    대강 알긴 알겠는데... 말그대로 '대강' 어떤 식이구나 만 이해해서 나중에 써먹어보기는 커녕 바로 잊어버릴 것 같았다. 

     

    그래서 알아보기로 했다!

    여기서 사용된 메서드, 속성 등.. 들 중에서 총 세 개!

     

    궁금증

    1. ... < - 는 정확히 뭐지? 

    1-2. ...order.toString() 을 사용하면 왜 각각의 숫자가 다 떨어져서 배열처럼 변하는거지?

    2. .matchAll() 

    3. 정규 표현식(정규식)은 도대체 뭐지? 어떻게 사용하는거지?

     

     

     

     


     

     

     

    1. ...  (MDN)

    ... < 이 점 세 개의 정체. 도대체 뭘까?

    지금까지는 배열인 경우에는 이렇게 앞에 점 세 개를 쓰세요~ 같은 '그렇게 써야 하니까'로 퉁치고 넘어갔었는데 (부끄러운 과거)

    이번에야말로! 잡고 넘어가기로 했다.

     

    MDN에 나와있는 친절한 설명으로는 이러하다.

    전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소 (배열 리터럴의 경우)로 확장하여, 0개 이상의 키-값의 쌍으로 객체로 확장시킬 수 있습니다. 

    = 배열이나 문자열과 같이 '반복 가능한 문자'를 확장시킬 수 있다. 

    로 이해했다 (그리고 얘 이름은 전개구문이구나!!!). 예문을 보면서 더 정확히 이해할 수 있었다.

     

    MDN 예문 👇

    var parts = ['shoulders', 'knees'];
    var lyrics = ['head', ...parts, 'and', 'toes'];
    // ["head", "shoulders", "knees", "and", "toes"]

    lyrics 배열 안에 자리한 parts 배열은 그대로 배열 형태를 유지하는 게 아니라 말그대로 전개되어서(펼쳐져서) 요소로 자리매김했다.

     

    좋아, 기초는 이해했다.

    그럼 두 번째 문제.

     

    전개 구문은 방금 알아봤듯이 '반복할 수 있는' 객체에 사용할 수 있다 ... 배열, 문자열, 객체와 같은.

    하지만 문제 속 order는 정수 타입이다.

    ...order을 사용해봤자 Error: Spread syntax requires ...iterable 같은 오류만이 나를 반긴다.

    (iterable-반복할 수 있는 객체가 아니라고 친절히 알려주는 것이다.)

     

    그렇기 때문에 .toString()이 등장한다. toString()은 문자열로 변환하여 반환해주는 메서드이다.정수타입인 order에 toString()을 사용하여 String 타입으로 변경한다. 문자열이 된 order에는 전개구문을 사용할 수 있다! 

     

    string 타입에 사용된 전개구문은 string을 쫙 펼쳐준다. *한 글자 씩*
    정수였던 order은 어느새 string 타입이 되어 한 글자씩 나뉘어진다. 
    이제 한 글자 한 글자 확인할 수 있는 상태가 된 것이다.

     

     

     

     


     

    2. matchAll() (MDN)

     

    (기초)

    문자열.matchAll(정규표현식)은 말그대로 정규표현식(조건)에 맞는 모든 요소들을 찾아 이를 배열로 만든다.

    여기서 중요한 건 정규 표현식(정규식)이다. matchAll() 메서드는 다음에 더 깊숙하게 알아보도록 하고, 메인인 정규 표현식을 알아보자.

     

     

     


     

     

     

    3. /[3|6|9]/g 의 정체, 정규 표현식 (MDN)

    정규 표현식(정규식)은 문자열에서 특정 문자 조합을 찾기 위한 패턴이다.

     

    어떻게 만들까?

    1. 정규 표현식 리터럴

    슬래시(' / ')로 패턴을 감싸주면 된다.

     

    2. 객체 생성자 호출

    const reg = new RegExp("(정규 표현식)");

     

    정규 표현식 패턴

    1. abc 같은 단순한 문자 (단순 패턴)

    문자열 있는 그대로를 탐색할 때 사용한다.

     

    예를들어 /abc/ 로 탐색한다면, "abc"가 정확히 들어있는 부분을 찾는다고 하면,

    -> ab c 같이 띄어쓰기(공백)가 포함되어 있거나

    -> acb 같이 순서가 뒤바뀐 것은 같은 문자열이라고 인정하지 않는다.  

     

    2. ab+c 같은 특수문자를 사용 

    - 하나 이상의 "b"를 찾을 때

    - 공백 문자를 찾을 때

    와 같은 직접적인 일치 이상의 탐색이 필요할 때 사용한다.

     

    예를들어

    (1. "a" 이후에 2. 0번 이상 "b"가 반복되어야 하고 3. 그 뒤에 "c" 가 있다) 라는 조건에 만족하는 문자열을 찾는다면

    /ab*c/ 라고 특수문자를 사용해 표현할 수 있다. 

     

    이 특수문자는 아주 다양하다. 그때그때 찾아보고 기억해야겠다.

     

     

    이스케이핑?

    만약에 특수문자를 패턴으로 사용하는 게 아니라, 특수문자가 문자열 안에 있는지가 궁금하다면 이스케이프한다.

    여기서 나오는 게 바로 역슬래시('\')!

    주의해야할 점은 특수문자에만 사용한다는 점이다. 

     

    예를들어

    "a*b" 라는 문자열을 찾고 싶다면 정규 표현식은 이렇게 써야한다. /a\*b/

    슬래시(/)를 찾고 싶은 경우에도 마찬가지 / \ / / (잘 보이게 하기 위해 일부러 띄어쓰기 했다)

    역슬래시를 찾고 싶다면? 마찬가지로 이스케이프 한다. / \ \ /

     

     

    플래그로 탐색하기

    양이 많지 않아서 MDN에서 가져왔다.

    플래그는 단독으로 사용할 수도, 순서에 상관 없이 여럿을 사용할 수도 있다는 점을 잊지말자. 

    const reg = /정규표현식/플래그;

    이와같은 구문으로 사용한다.

     

     

    그럼 다시 풀이로 돌아가서 사용된 정규 표현식을 해석해보자.

    /[3|6|9]/g

    1. 슬래시로 감싸져 있는 것을 보아 정규 표현식을 사용했다.

    2. [] 는 괄호 안 조건이 부분적으로라도 맞는 문자열을 찾는다는 의미.

    3. 괄호 안 조건인 3 | 6 | 9 는 |를 사용하여 3 or 6 or 9

    4. 마지막 플래그 g 는 전역 탐색, 즉 조건과 일치하는 모든 것을 찾는다. 

    (만약 플래그 g를 사용하지 않으면 조건에 일치하는 제일 첫번째 값만 찾아낸다)

     

     


     

     

     

    지금까지는 다른 사람 풀이를 보고 이렇게도 풀 수 있구나 ... 라고 놀라면서도 한 번 써보고 이해하는 정도로 끝냈다.

    이번에는 저 풀이 자체에 모르는 게 너무 많아서(ㅎ..) 조각조각 내서 알아보았다.

    생각보다 오래걸렸지만 꼭꼭 씹어 넘긴 거 같아 뿌듯하다.

    위에서도 말했지만 이제는 여러 메서드들을 써보고 응용하려고 노력하면서 문제를 풀고 있다. 

    이번에 정리한 내용도 꼭 응용할 수 있기를 바라면서. 이만 글을 줄인다. 총총~ 

     

     

     

     

     

     

     

    댓글

Designed by Tistory.