TIL/알고리즘 공부

프로그래머스 Lv. 2 Swift 알고리즘 - [3차] 압축

여의도사노비 2023. 1. 11. 00:38
728x90

문제의 규칙을 찾는데 시간이 오래 걸렸다..!

K다음 KA가 오는데 만약 KA가 있으면 KAK를 찾아봐야한다.

그런데 KAK가 있으면? 사전에서 KAKO를 찾아봐야한다.

 

이렇게 한단어씩 확인하고 다음 단어가 길어지고... 하는 규칙을 일반화 하는 것이 까다로웠다.

 

 

이 문제를 풀면서 생각한 논리적 흐름

  1. 먼저 알파벳과 그에 따른 인덱스를 나타내줄 수 있는 딕셔너러리를 만든다.
  2. 알파벳은 unicode를 이용하여 만들어주고 그 유니코드로 만들어진 알파벳 배열에 for문을 사용하여 인덱스 value를 만들어준다.
  3. dictIndex는 26번째 알파벳인 z 다음에 쓰일 위치라 27로 선언한다.
  4. arrMsg에서 알파벳을 가져오되 만약 그 알파벳이 사전에 위치한 알파벳이라면 i에 1을 계속 더하여 알파벳의 길이를 늘려준다.
  5. 그러다가 사전에 없는 연속된 알파벳이 나오면 dictIndex에 1을 추가해 위치를 수정해주고
  6. 그 사전에 없는 연속된 알파벳을 dict에 저장한다. 그리고 해당 알파벳 전의 알파벳 value값을 result에 저장한다.(removeLast로 삭제 -> 전 알파벳 밸류)
  7. 이를 반복하면 끝!

 

 

* 코드

func solution(_ msg:String) -> [Int] {
    let words = (65...90).map({"\(UnicodeScalar($0)!)"})
    let arrMsg = Array(msg)
    let len = arrMsg.count
    var count = 1
    var dict: [String: Int] = [:]
    var dictIndex = 27
    var result = [Int]()
    var i = 0
    
    for i in words {
        dict[i] = count
        count += 1
    }
    
    while i < len {
        var word = "\(arrMsg[i])"
        
        while true {
            if dict[word] != nil {
                i += 1
                
                if i == len {
                    result.append(dict[word]!)
                    break
                }
                
                word.append(arrMsg[i])
            } else {
                dict[word] = dictIndex
                dictIndex += 1
                _ = word.removeLast()
                result.append(dict[word]!)
                break
            }
        }
    }
    return result
}

 

 

정리(Today I Learned)

  1. 이전에 다른 문제를 풀때 알파벳을 직접 나열하여 푼 적이 있다. 그 당시 그게 너무 귀찮아서 구글링을 좀 해보니 Unicode를 사용하는 방법이 있었다. 앞으로도 이렇게 이용해야겠다!
  2. removeFirst와 removeLast가 왜 있는지 옛날엔 잘 몰랐는데... 요즘 스택/큐 문제들을 풀다보니 이유를 알겠다. 결국 자료구조상 FIFO, LIFO 특성을 가진 스택/큐를 쓸 수 밖에 없는데, 이를 유용하게 쓰기위해 일부로 First, Last를 만들어놓은 것이었다..!
  3. while이나 for나 중첩되면 너무 헷갈린다... 최대한 중첩하지 않고 풀 수 있도록 정진해야겠다.