본문 바로가기

2.알고리즘/프로그래머스

[JS] 프로래머스 숫자 문자열과 영단어

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

 

프로그래머스

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

programmers.co.kr

 

제출 코드

 

function solution(s) {
    if(s === "") return ""
    if(!isNaN(s)) return Number(s)
    const target = ["zero","one","two","three","four","five","six","seven","eight","nine"]

    for(let i = 0; i < 10; i++){
        s = s.split(target[i]).join(i)
    }
    return Number(s)
}

 

포인트라고 생각한 부분은

1."숫자가 아닌 것들을" 어떻게 찾을 것인가. -> isNaN 메서드를 사용

2."문자열들을" 어떻게 바꿀 것인가 -> replace를 사용

 

첫 번째 생각한 과정은

1. 문자열을 배열화한다(split) -> 글자별로 나눈다

2. 배열을 순회하여, 숫자가 나올 때 리턴을 한다

3. 숫자가 아니면 다음 것도 순회한다

4. 숫자를 찾은 순간 지금까지 순회한 자료를 매칭 함수로 보낸다

그 후, 배열을 다시 문자 열화 시킨다 였습니다.

 

const input = "one4seveneight"

const arr = input.split("")
let result = []

// arr.forEach(e => console.log(!isNaN(e)))

const toString = str => {
    if(str === "one") return 1
    if(str === "seven") return 7
    if(str === "eight") return 8
}

const test = arr.reduce((acc,cur,idx,array) => {
    console.log(acc)
    if(!isNaN(cur)){
        result.push(toString(acc))
        result.push(Number(cur))
    }
    return acc+cur
},"")
console.log(result)



console.log(input.includes("one"))

 

풀이 방법을 다양하게 고민한 코드입니다. 문자열을 받아 숫자를 리턴하는 함수 toString과

 

reduce를 사용해서 원소를 순회하다가 숫자를 만난 경우 그전까지 잘라서 매칭을 시키려고 했습니다. 

 

여기서, 문제가 발생했는데 -> 숫자가 하나도 없이 전부다 문자열로 들어온 경우 조건이 망가졌습니다.

 

ex) "onetwothree" -> 구분 숫자가 없음

 


굳이, 배열로 변경해야하나 싶어서 문자열을 바꾸는 함수를 생각해보니 replace를 사용하면 쉽지 않을까라는 생각이 들어

 

바꿔야 할 대상은 정해져 있으니 배열화 시켜서 반복문을 돌렸습니다. 

 

최초 테스트 케이스에선 문제가 없었는데,

 

function solution(s) {
    // console.log(typeof Number(s))
    // if(s === "") return ""
    // if(!isNaN(s)) return Number(s)

    const target = ["zero","one","two","three","four","five","six","seven","eight","nine"]

    for(let i = 0; i < 10; i++){
        s = s.replace(target[i], i)
    }
    console.log(s)
    return Number(s)
}
solution()

안 보이는 테스트 케이스에서 문제가 생기는 걸 발견했고, "oneone"처럼 같은 문자열이 2개 이상 들어온 경우

replace가 한 개만 바뀐다는 문제를 파악하였습니다

 


replaceAll을 찾아보았는데, replaceAll은 최신에 추가 / 본인이 구현 / 정규표현식 사용 등으로 나뉘었으며

 

정규표현식 내에서 변수사용하는 법을 찾다가

 

https://guseowhtjs.tistory.com/entry/%EC%A0%95%EA%B7%9C%EC%8B%9D%EC%97%90%EC%84%9C-%EB%B3%80%EC%88%98%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%A9%EB%8B%88%EA%B9%8C

 

정규식에서 변수를 어떻게 사용합니까?

질문자 :JC Grubbs String.replaceAll() 메서드를 만들고 싶습니다. 정규식을 사용하는 것이 가장 간결한 방법이라고 생각합니다. 그러나 정규식에 변수를 전달하는 방법을 알 수 없습니다. 나는의 모든

guseowhtjs.tistory.com

 

블로그의 Gracenotes 부분을 보고

 

'ABABAB'.split('B').join('A')
//AAAAAA

예제를 확인하고, replace메서드를 사용할 필요 없이 위로 대체하면 되겠다 생각했고, 통과하였습니다.

 

 

 

좋아요를 많이 받은 코드랑 비슷했습니다.

 


자체적 피드백

 

1. 반복문의 조건식을 고정값으로 사용한 게 아쉽다. -> 목표하는 배열의 값이 바뀌게 되면, 조건식의 값도 변경되게 될 텐데

 

length 프로퍼티를 사용하는 게 나을 것 같습니다. (유지 보수성) 

 

2. for문 말고 고차 함수나 다른 순회 문을 적용하지 못한 게 아쉽다. -> 퍼포먼스는 측정해봐야 알겠지만

 

적용을 안 한 게 아니라 못했기 때문에 아쉽습니다. 다른 풀이를 보았을 때, 고차 함수를 적용시킬 수 있을 예제였습니다.

 

3. 자료구조를 사용하지 않고 목표를 정할 수 없었을까? -> 다른 풀이에 객체화, 배열화 시킨 것은 있었는데

따로 방법은 없는 것 같습니다.

 

4. 방어 코드를 넣으려고 한 점은 잘했다고 생각합니다. 문자열이 최소 1개는 들어오기 때문에 첫 번째는 의미가 없었으나

문제 조건이 변하게 되면 의미를 갖게 될 것 같고, 두 번째는 입출력 예제의 5번을 보면 "123"으로 변경이 필요 없는 코드가 들어오게 되면 반복문을 실행시키지 않으니 잘한 게 아닐까 싶습니다.

 

5. return문에 + 연산자를 사용할 수 있겠지만(형 변환) 가독성을 위해 작성하지 않았습니다. 


배운 점은 replace를 사용하지 않고 문자열 전체를 변경시키는 방법인데, 알고 있다고 생각했던 split과 join을 이용하였을 때 응용이 가능하다는 점입니다.

 

반응형

'2.알고리즘 > 프로그래머스' 카테고리의 다른 글

[JS]신규 아이디 추천  (0) 2022.08.24
[JS]소수 만들기  (0) 2022.08.19
빅오 표기법(Big-o Notation)  (0) 2022.04.14
[JS] 프로그래머스 K번째 수  (0) 2021.06.24
[JS]음양 더하기  (0) 2020.02.04