적당한 고통은 희열이다

- 댄 브라운 '다빈치 코드' 중에서

Algorithm/Programmers

[Swift 알고리즘] Programmers 옹알이

hongssup_ 2022. 10. 28. 20:07
반응형

Level 1 연습문제 

옹알이

문제 설명
머쓱이는 태어난 지 11개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음과 네 가지 발음을 조합해서 만들 수 있는 발음밖에 하지 못하고 연속해서 같은 발음을 하는 것을 어려워합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요.
제한사항
- 1 ≤ babbling의 길이 ≤ 100
- 1 ≤ babbling[i]의 길이 ≤ 30
- 문자열은 알파벳 소문자로만 이루어져 있습니다.

입출력 예시

print(solution(["aya", "yee", "u", "maa"])) //1
print(solution(["ayaye", "uuu", "yeye", "yemawoo", "ayaayaa"])) //2
print(solution(["aya", "yee", "u", "maa", "wyeoo"])) //1

 

답안

import Foundation

func solution(_ babbling:[String]) -> Int {
    let words = ["aya", "ye", "woo", "ma"]
    var result = 0

    for i in babbling {
        var bab = i
        for j in words {
            if bab.contains(j + j) { break }
            bab = bab.replacingOccurrences(of: j, with: ".")
        }
        if bab.filter({ $0 == "." }).count == bab.count {
            result += 1
        }
    }
    
    return result
}

 

무지성 조건문으로 문제를 풀다가 이거는 아닌것 같아서 흰트를 봐버렸다..

replacingOccurrences(of: , with: )를 사용해서 간단하게 풀 수 있는 문제였다. 

 

처음에는 아예 다 replacingOccurrences 사용해서 다음과 같이 옹알이가 두 개 연속되는 건 "x"로 치환하고, 하나씩 있는 것만 "."로 치환해준 후, 최종적으로 "." 를 ""로 치환해준 후, 해당 단어에 알파벳이 없으면 1을 더하도록 해주었다. 

처음부터 ""로 치환하지 않고, "."로 치환해준 후 ""로 다시 해주는 건 wyeoo 처럼 중간에 섞여 있을 경우, ye가 ""으로 치환된 후 "woo"만 남으면 유효한 말로 잘못 계산될 수 있기 때문.   

for j in words {
    bab = bab.replacingOccurrences(of: j + j, with: "x") 
    bab = bab.replacingOccurrences(of: j, with: ".")
}
bab = bab.replacingOccurrences(of: ".", with: "")
if bab.isEmpty { result += 1 }

그런데 replacingOccurrences 를 사용하여 string을 치환하는 작업이 생각보다 시간이 걸리는 작업인 것 같더라.

그래서 이거는 한번만 사용을 할 수 있도록, 중복 옹알이가 들어있을 경우에는 아예 break를 해서 다음 단어로 넘어갈 수 있도록 해 주었고

마지막에 ""으로 치환하는 부분도 그냥 "."의 갯수와 단어의 길이가 동일할 경우 result += 1 을 해주는 것으로 변경하였더니 
테스트 케이스마다 차이는 있어도, 대체로 시간이 좀 더 단축된 걸 볼 수 있었다. 

 for j in words {
    if bab.contains(j + j) { break }
    bab = bab.replacingOccurrences(of: j, with: ".")
}
if bab.filter({ $0 == "." }).count == bab.count {
    result += 1
}

왼쪽이 변경 전, 오른쪽이 변경 후

다른 답안

replacingOccurrences 를 쓰면 코드 가독성과 이해가 쉽지만, 시간이 오래 걸리는 것 같아 다른 방법도 한번 찾아보았다.

알파벳 하나마다 확인을 해주며, 유효한 옹알이가 나올 경우 배열에 추가해주는 방법이다. 

배열.last 를 쓰면 빈 배열이라도 nil값을 반환해주는구나. 

확실히 시간적으로는 replacingOccurrences 안쓰고 푸는게 훨씬 빠르긴 하구만

func solution(_ babbling:[String]) -> Int {
    let words = ["aya", "ye", "woo", "ma"]
    var result = 0

    for i in babbling {
        var bab = i
        var valid = [String]()
        var word = ""
        for b in bab {
            word = word + String(b) 
            if words.contains(word) && valid.last != word {
                valid.append(word)
                word = ""
            } 
        }
        if word == "" {
            result += 1
        }
    }
    return result
}

728x90
반응형