NIRVANA
[level 1] 숫자 문자열과 영단어(성공...? 다시) 본문
문제
네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.
다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.
- 1478 → "one4seveneight"
- 234567 → "23four5six7"
- 10203 → "1zerotwozero3"
이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.
문제 풀이 접근법1
1) 문자열 s에 num_list(1~9까지 영어로 되어 있는 리스트)의 단어가 포함되어 있는지 확인한다.
2) 만약 문자열이 없다면 숫자로 바꾼 뒤 return한다.
3) 문자열 s에서 숫자로 변환 가능한 문자가 있는지 확인한 뒤, 있다면 answer 리스트에 추가한다.
4) 문자열 s를 특정 크기만큼 슬라이싱 한 다음, 슬라이싱 된 단어에 num_list의 단어가 포함되어 있는지 확인한다.
5) 포함된 단어를 문자열 answer에 추가한다.
6) answer의 문자가 숫자로 변환이 가능한 문자라면 number 리스트에 숫자로 변환한 뒤 추가한다.
7) answer에 있는 문자열 중에서 num_list에 있는 문자가 포함되어 있다면 해당 리스트에 해당하는 숫자를 number리스트에 추가한다.
num_list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
answer = []
number = []
if s.isdigit():
print(int(s))
for i in s:
if i.isdigit():
answer.append(i)
for i in range(len(s)):
#print(s[i:i+5])
if s[i:i+5] in num_list:
#if s[i:i+5].contains(num_list[i]):
answer.append(s[i:i+5])
for i in range(len(answer)):
if answer[i].isdigit():
number.append(int(answer[i]))
for j in range(len(num_list)):
#print(type(answer[i]))
if answer[i] in num_list[j]:
number.append(j+1)
print(number)
예상하지 못한 숫자의 중복이 발생한다는 문제점이 있는 코드였다.
문제 풀이 접근법2
문제 풀이 접근법1과 비슷하게 진행하되, 처음부터 숫자로 변경 가능한 문자는 숫자로 변환하여 answer 리스트에 추가하였다.
그 후, 리스트를 set으로 형변환 하여 중복을 제거한다.
다음 sort()로 오름차순 정렬을 한 뒤, 다시 문자열로 변환하고, 문자열을 int형으로 변환하여 반환한다.
def solution(s):
answer = []
num_list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
if s.isdigit():
print(int(s))
for i in range(len(s)):
if s[i].isdigit():
answer.append(int(s[i]))
for i in range(len(s)):
for j in range(len(num_list)):
if num_list[j] in s[i:i+5]:
answer.append(j+1)
answer = list(set(answer))
answer.sort()
answer = list(map(str, answer))
return int(''.join(answer))
샘플 테스트 케이스는 다 통과했는데, 테스트 케이스에서 1번빼고 다 실패가 나왔다.
다시 생각을 해보니 onetwothree344와 같이 문자열 자체에서 중복이 있는 경우에도
중복을 다 제거하기 때문에 그렇다는 걸 알았다.
문제 풀이 접근법3
필요한 중복을 반영하기 위해 set으로 리스트를 형변환하는 과정을 두지 않고 대신 if num_list[j] not in answer: 조건문을 활용하여 불필요한 중복(배열 슬라이싱으로 인해 발생하는)은 거르고, 필요한 중복은 반영하고자 했다.
def solution(s):
answer = []
num_list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
number = []
if s.isdigit():
print(int(s))
for i in range(len(s)):
if s[i].isdigit():
number.append(int(s[i]))
for i in range(len(s)):
for j in range(len(num_list)):
if num_list[j] in s[i:i+5]:
if num_list[j] not in answer:
answer.append(num_list[j])
for i in range(len(answer)):
for j in range(len(num_list)):
if answer[i] in num_list[j]:
number.append(j+1)
number.sort()
number = list(map(str, number))
return int(''.join(number))
해당 코드의 반례는 oneoneone이다.
풀이 2에서는 숫자와 문자의 조합으로 된 중복도 제거했다면 해당 코드에서는 숫자와 문자의 조합으로 된 중복은 제거하지 않았다. 다만 이렇게 문자로 중복되는 경우에는 if num_list[j] not in answer에서 걸러지기 때문에 중복을 반영하지 못한다.
문제 풀이 접근법4
문자열 s에 포함된 영단어가 나오는 개수를 확인 한뒤, 그만큼을 곱해주어 더하는 코드로 수정을 해보았다.
def solution(s):
num_list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
answer = []
number = []
if s.isdigit():
print(int(s))
for i in s:
if i.isdigit():
number.append(i)
for i in range(len(s)):
for j in range(len(num_list)):
if num_list[j] in s[i:i+5]:
if num_list[j] not in answer:
n = s.count(num_list[j])
answer.append(num_list[j])
number.append(str(j+1) * n)
number.sort()
return int(''.join(number))
역시나...계속 실패가 떴다. ^_ㅜ
문제에 0도 포함인데 그걸 빼서 그런거였다...그래서 수정은 했는데
def solution(s):
num_list = [ 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
answer = []
number = []
if s.isdigit():
print(int(s))
for i in s:
if i.isdigit():
number.append(i)
for i in range(len(s)):
for j in range(len(num_list)):
if num_list[j] in s[i:i+5]:
if num_list[j] not in answer:
n = s.count(num_list[j])
answer.append(num_list[j])
number.append(str(j) * n)
number.sort()
return int(''.join(number))
이 망할놈의 파이썬이 앞에 있는 0은 숫자로 바꾸면서 다 없앴다...^~^
성격 안좋아질 것 같아서 포기
나중에...다시 풀어보겠음 아 쫭나
(딕셔너리...랑 replace를 사용해서 다시 코드 짜보자 ^_^)
문제 풀이 접근법5(성공!)
구글에 서치를 해보니까...^_^
대부분 dictionary와 replace를 사용해서 문제를 푸신 듯 했다.
그래서 나도 dictionary와 replace를 사용해서 문제를 풀었다. 처음에는 dictionary의 value값을 그냥 int형으로 했는데 (당연히) replace에서 오류가 났다. 그래서 value값도 문자로 변경한 후, 마지막에 int()로 바꿔주었다.
def solution(s):
num_dic = {
'zero':'0', 'one': '1', 'two':'2', 'three':'3', 'four':'4', 'five':'5',
'six':'6', 'seven':'7', 'eight':'8', 'nine':'9'
}
for num in num_dic:
s = s.replace(num, num_dic[num])
return int(s)
해당 코드 역시 0은 없어졌다...
아마 그냥 진짜 내 코드에 오류가 있었나보다...
내일(=0729) 코드 뜯어보면서 틀린 부분 찾아봐야겠다..
'Coding test(Python3) > Programmers' 카테고리의 다른 글
[level 1] K번째수 (0) | 2023.07.29 |
---|---|
[level 1] 문자열 내 마음대로 정렬하기 (0) | 2023.07.29 |
[level 1] [1차] 비밀지도(비트 연산자로 다시 생각해보기) (0) | 2023.07.25 |
[level 1] 크기가 작은 부분 문자열 (0) | 2023.07.25 |
[level 1] 시저 암호 (mod로 다시 생각해보기) (0) | 2023.07.24 |