개발/PS

[Swift] 프로그래머스 Lv2 문자열 압축

유훈 | Yuhun 2022. 6. 20. 20:44
반응형

같은 2단계여도 확실히 Kakao 문제가 난이도가 있는 느낌입니다.

문자열을 다루는데 도움이 될 듯한 문제여서 따로 포스팅합니다.

import Foundation

func solution(_ s:String) -> Int {
    var result:Int = s.count // 가장 짧은 길이 저장
    if result == 1 {return 1}
    for i in 1...s.count/2 {
        var temp:String = "" // 임시 메모리
        var diviedNumber:Int = s.count/i // 문자 길이를 나눈 몫 -> 분할 덩어리
        var remainNumver:Int = s.count%i // 남은 길이를 붙여줄 문자 길이
        var duplicateCount = 1 // 문자열 압축 횟수
        for j in 0..<diviedNumber { // 첫번째 덩이리부터 비교 횟수 -> 몫 만큼
            var str = s[s.index(s.startIndex, offsetBy: i*j)..<s.index(s.startIndex, offsetBy: (j+1)*i)]
            
            if j == diviedNumber-1 { // 마지막 문자열 예외처리(예외처리)
                if duplicateCount == 1 {
                    temp += str
                } else {
                    temp += "\(duplicateCount)\(str)"
                    duplicateCount = 1
                }
                break
            }
            
            var checker:Bool = (s[s.index(s.startIndex, offsetBy: i*j)..<s.index(s.startIndex, offsetBy: (j+1)*i)] == s[s.index(s.startIndex, offsetBy: i*(j+1))..<s.index(s.startIndex, offsetBy: (j+2)*i)] )
            
            if checker {
                duplicateCount += 1
            } else {
                if duplicateCount == 1 {
                    temp += str
                } else {
                    temp += "\(duplicateCount)\(str)"
                    duplicateCount = 1
                }
            }
        }
        temp += s[s.index(s.endIndex, offsetBy: -remainNumver)..<s.endIndex]
        
        if temp.count < result {
            result = temp.count
        }
    }

    return result
}

제가 구현한 방법은 문자를 길이별로 자르고 비교해 압축된 문자열을 만들고 남는 문자를 맨 마지막에 붙여주었습니다.

이후 그 전에 압축한 문자열과 비교해 더 적은 수의 문자열을 채택하는 방식입니다.

 

구현은 String을 index별로 구간을 나누고 비교해서 압축된 문자열을 만들었습니다. index의 범위를 잘 생각해서 비교해야 에러없이 정확한 문제를 만들 수 있었습니다.

 

문자를 3개씩 나눴다고 가정하고 중요한 부분은 마지막 비교에선 문자를 그대로 temp에 붙여준 것입니다.

예를 들어aaaaaaaaaaaa를  aaa(0) aaa(1) aaa(2) aaa(3) 로 나눴다면 처음 세번의 비교는 0,1 / 1,2 / 2,3 을 비교하지만 마지막 비교는 3,4를 비교하게 되고 out of range로 잘못된 배열의 접근이 이루어져 런타임 에러가 발생합니다.
때문에 마지막 비교 전에 지금까지 앞에서 중복 값을 확인한 후에 문자를 붙여주었습니다.

 

또다른 예외 처리로는 만약 문자열이 1이면 그대로 1을 리턴하게 했습니다. 제가 구현한 것은 1이 들어오면 for문에서 1...0이라는 범위를 가지기에 런타임 에러가 발생합니다.

 

Swift에선 String을 다루는 것이 좀 길고 어려운데 index()만 잘 익힌다면 사용할 만한 듯합니다.

반응형