알고리즘

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

작은코딩 2022. 4. 22. 02:56

문제

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

 

코딩테스트 연습 - 숫자 문자열과 영단어

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다. 다음은 숫자의 일부 자

programmers.co.kr

네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.

  • 1478 → "one4seveneight"
  • 234567 → "23four5six7"
  • 10203 → "1zerotwozero3"

이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.

참고로 각 숫자에 대응되는 영단어는 다음 표와 같습니다.

 

숫자 영단어
0 zero
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine

제한사항

  • 1 ≤ s의 길이 ≤ 50
  • s가 "zero" 또는 "0"으로 시작하는 경우는 주어지지 않습니다.
  • return 값이 1 이상 2,000,000,000 이하의 정수가 되는 올바른 입력만 s로 주어집니다.

입출력 예

 

s result
"one4seveneight" 1478
"23four5six7" 234567
"2three45sixseven" 234567
"123" 123

입출력 예 설명

입출력 예 #1

  • 문제 예시와 같습니다.

입출력 예 #2

  • 문제 예시와 같습니다.

입출력 예 #3

  • "three"는 3, "six"는 6, "seven"은 7에 대응되기 때문에 정답은 입출력 예 #2와 같은 234567이 됩니다.
  • 입출력 예 #2와 #3과 같이 같은 정답을 가리키는 문자열이 여러 가지가 나올 수 있습니다.

입출력 예 #4

  • s에는 영단어로 바뀐 부분이 없습니다.

제한시간 안내

  • 정확성 테스트 : 10초

풀이

요구사항 파악

- 영단어가 들어있는 (혹은 숫자만) 매개변수를 원래 숫자로 바꿔서 리턴하기

input type : str

output type : int

 

문제 정의

1. 문자를 숫자로 바꿔주기

2. 숫자만 있을 때 예외처리를 해야 하는가?

 

문제 해결 방법

1. 문자를 숫자로 바꿔주기

 - 바꿔야 할 문자와 숫자를 dictionary 형태로 저장 Dict[str, str]

 - items, replace 함수를 이용해서 dictionary에 저장된 문자를 바꿔준다. (반복문 사용)

 

2. 숫자만 있을 때 예외처리를 해야 하는가?

 - 더 이상 바꿀 문자가 없을 때 반복문을 탈출해서 불필요한 반복문을 수행하지 않는게 효율적인 코드라고 생각하지만 지금 상황에서는 dictionary의 길이가 10으로 작다고 판단되기에 매 반복문을 실행할 때 더이상 바꿀 문자가 있는지 없는지 확인하는 과정이 오히려 비효율적일 수 있다고 판단했다.

 

문제 해결 / 코드

s = "2three45sixseven" # 제출할 때 삭제 (테스트용)

num_dict = {
    "zero": "0",
    "one": "1",
    "two": "2",
    "three": "3",
    "four": "4",
    "five": "5",
    "six": "6",
    "seven": "7",
    "eight": "8",
    "nine": "9",
}
def solution(s):
    for k, v in num_dict.items():
        s = s.replace(k, v)
    return int(s)

solution(s) # 제출할 때 삭제 (테스트용)

 

피드백

코드를 완성하고 다른 사람의 풀이를 확인하러 넘어갔는데 내가 쓴 코드랑 비슷한 코드가 좋아요를 가장 많이 받은 풀이법이어서 놀랐다. (이런 적은 처음이야,,)

문제는 해결했지만 문제 정의의 2번을 테스트해서 어떤 방법이 더 효율적인지 확인해 보기로 했다. 

 

더 이상 바꿀 문자가 없는지 확인하는 코드

s = "2three45sixseven"

num_dict = {
    "zero": "0",
    "one": "1",
    "two": "2",
    "three": "3",
    "four": "4",
    "five": "5",
    "six": "6",
    "seven": "7",
    "eight": "8",
    "nine": "9",
}
def solution(s):
    for k, v in num_dict.items():
        try:
            int(s)
            break
        except ValueError:
            pass
        s = s.replace(k, v)
    return int(s)

solution(s)

왼쪽 : 예외처리 x, 오른쪽 :예외처리 o

s = "2three45"
s = "2three45sixseven"

두 가지 경우를 테스트해봤는데 모두 예외처리를 하는 경우가 더 시간이 걸렸다. 그래도 예외처리를 하는 경우가 시간이 적게 걸릴 줄 알았는데,, 혹시나 싶어 "1234" 같이 전부 숫자로 넣어 테스트를 해봤지만(반복문 1회 차에서 바로 break) 결과는 같았다. 

시간 복잡도에 대한 부분은 내가 잘 몰라서 정확한 진단은 할 수 없지만 try except가 추가됨으로 인해서 시간 복잡도가 커졌구나 추측할 따름이다. 

 

도전 과제

1. try except를 이용했을 때 왜 시간이 더 오래 걸리는지 공부하기

2. try except가 아닌 다른 방법으로 예외처리를 했을 때 결과 확인하기