NIRVANA

[level 1] 숫자 문자열과 영단어(성공...? 다시) 본문

Coding test(Python3)/Programmers

[level 1] 숫자 문자열과 영단어(성공...? 다시)

녜잉 2023. 7. 26. 16:49

문제

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

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

  • 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) 코드 뜯어보면서 틀린 부분 찾아봐야겠다..