TIL/알고리즘 공부

프로그래머스 Lv. 2 Swift 알고리즘 - [1차] 뉴스 클러스터링

여의도사노비 2023. 1. 9. 11:55
728x90

카카오 블라인드 문제를 못풀면... 기분이 안좋다... ㅠㅠ

[1차]인거 보면... 어렵지 않은 문제라고 생각하고 출제되었을텐데... 나는 왜 못풀었는가...?

 

중간정도는 답을 찾는 과정에 근접했다고 생각하지만 결국 끝을 맺지 못했다! 그래서 여러 블로그를 참고하였는데 내가 생각했던 방식의 접근과 가장 유사했던 분이 계셔서 그 분의 블로그를 참고했다.

 

(참고한 블로그: https://velog.io/@aurora_97/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-1%EC%B0%A8-%EB%89%B4%EC%8A%A4-%ED%81%B4%EB%9F%AC%EC%8A%A4%ED%84%B0%EB%A7%81-Swift)

 

 

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

  1. 먼저 짚고 넘어가야할 옵션들부터 해결하였다. lowercased를 사용하여 대소문자를 통일하였고
  2. 그렇게 통일 시켰을 때 만약 배열의 값이 똑같다면 65536을 바로 리턴해주면 됐다.
  3. 또한 알파벳이 아닌 특수문자, 공백, 기호 등이 들어갈 경우 한 번 더 걸러서 알파벳 원소들의 조합만 남길 수 있도록했다.
  4. 그 다음 과정에서 원소들이 배열들이 몇개나 중복되는지 Dictionary를 이용해서 걸러주었다.
  5. 이 다음 과정으로 arrFirst와 arrSecond간의 intersection(교집합), sumofset(합집합)을 구하고 그 구해진 원소들의 개수를 dictionary로 파악하고자 했다.
  6. 그 후 나온 원소들의 개수로 자카드 유사도 방식의 값을 내고자 했다.
  7. 하지만 5~6 과정이 너무 복잡하여 오랜 고민을 하다가 다른 블로거 분들의 코드를 봤다.
  8. 참고한 블로거분의 코드는 lowercased부터 알파벳 확인까지 모두 딕셔너리를 만드는 함수 안에 넣어 굉장히 깔끔하게 진행하셨고
  9. intersectionCount 이 부분이 적어놓은 코드만 보면 오 그렇네 맞네 이런 생각이 절로 드는데... 내가 막상 하려고하면 뇌가 정말 가렵다...
  10. 결론은 이 분도 딕셔너리의 키 값을 이용해 공통된 키 값의 value중 min과 max를 사용하여 값을 구하셨다.

 

 

* 내가 적은 틀린 코드

func solution(_ str1:String, _ str2:String) -> Int {
    let first = Array(str1.lowercased().map{String($0)})
    let second = Array(str2.lowercased().map{String($0)})
    var arrFirst: [String] = []
    var arrSecond: [String] = []
    var dictFirst: [String: Int] = [:]
    var dictSecond: [String: Int] = [:]
    var intersection: Set<String> = []
    var sumSet: Set<String> = []
    
    if first == second {
        return 65536
    }
    
    for i in 0...first.count-2 {
        let temp = String(first[i]) + String(first[i+1])
        if isAlphabet(temp) {
            arrFirst.append(temp)
        }
    }
        
    for i in 0...second.count-2 {
        let temp = String(second[i]) + String(second[i+1])
        if isAlphabet(temp) {
            arrSecond.append(temp)
        }
    }
    
    for i in arrFirst {
            if dictFirst[i] != nil {
                dictFirst[i]! += 1
            } else {
                dictFirst[i] = 1
            }
        }
    
    for i in arrSecond {
            if dictSecond[i] != nil {
                dictSecond[i]! += 1
            } else {
                dictSecond[i] = 1
            }
        }
    
    return 0
}

func isAlphabet(_ str: String) -> Bool {
  for char in str {
    if !char.isLetter { return false }
  }
  return true
}

 

 

 

* 참고한 답안 코드

import Foundation

func makeDict(_ str: String) -> [String: Int] {
    let str = Array(str)
    let len = str.count
    
    var result = [String: Int]()
    
    for i in 0..<len-1 where str[i].isLetter && str[i+1].isLetter {
        let key = String([str[i], str[i+1]]).lowercased()
        if result[key] == nil { result[key] = 0 }
        result[key]! += 1
    }
    
    return result
}

func solution(_ str1:String, _ str2:String) -> Int {
    let mux: Double = 65536
    
    let s1 = makeDict(str1)
    let s2 = makeDict(str2)
    
    let s1Key = Set(s1.keys.map { String($0) })
    let s2Key = Set(s2.keys.map { String($0) })
    
    let commonKey = s1Key.intersection(s2Key)
    let sumKey = s1Key.union(s2Key)
    
    let intersectionCount = commonKey.reduce(0) { partialResult, key in
        partialResult + min(s1[key]!, s2[key]!)
    }
    
    let unionCount = sumKey.reduce(0) { partialResult, key in
        partialResult + max(s1[key] ?? 0, s2[key] ?? 0)
    }
    
    if unionCount == 0 { return Int(mux) }
    return Int(Double(intersectionCount)/Double(unionCount) * mux)
}

 

 

정리(Today I Learned)

  1. 알고리즘 문제 풀기는 너무 어렵지만 항상 한끝 차이다. 수학 문제랑 똑같다... 많이 풀고 틀린거 다시 보고 정말 기초적인 원리를 알고.
    이 세가지를 앞으로 3개월만 반복해보자!