Swift랑 친해지기/programmers 풀기

[프로그래머스] [1차]뉴스 클러스터링 (Swift)

데브킹덕 2022. 11. 21. 19:33

https://school.programmers.co.kr/learn/courses/30/lessons/17677

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

변수

  • alphabet = AtoZ를 가진 문자열 배열
  • str1 = 매개변수 str1 문자열을 한 문자씩 배열에 담은 문자열 배열
  • str2 = 매개변수 str2 문자열을 한 문자씩 배열에 담은 문자열 배열
  • str1Array = str1배열 중 알파벳으로 이루어진 문자열만 담은 문자열 배열 
  • str2Array = str2배열 중 알파벳으로 이루어진 문자열만 담은 문자열 배열
  • intersectionArray = str1Array와 str2Array의 교집합을 담은 문자열 배열
  • indexArray = str2Array요소 중 str1Array와 같은 문자열일때 str2Array의 인덱스를 담는 Int형 배열
  • count = str1Array와 str2Array가 같을때 1을 증가시켜 str2Array의 추후 요소에 접근할때 교집합에 담지 않기 위한 Int형 변수
  • unionArray = str1Array와 str2Array를 더한뒤 intersectionArray(교집합)을 뺀 문자열 배열, 합집합 배열
  • intersection = intersectionArray 배열의 요소의 개수, 교집합 개수
  • union = unionArray 배열의 요소의 개수, 합집합 개수
  • answer = 교집합 / 합집합 * 65536 계산 한 Double형 상수

 

 

나만의 풀이

1.  str1, str2를 매핑하여 한문자씩 접근하였다. 

 

2. 입력으로 들어온 문자열은 두 글자씩 끊어서 다중집합 원소로 만들기 위해

for in 반복문을 이용해  모든요소에 접근했고, uppercased메서드를 이용해 모든 요소를 대문자로 바꾸어 비교하였다.

이때 현재 index와 다음 index가 alphabet함수에 포함되어 있으면 str1Array와 str2Array에 .append 메서드를 이용하여 추가하였다.

 

3. str1Array와 str2Array를 .sorted 메서드를 이용해 정렬하였을때 서로 같은 집합(공집합)이면 자카드 유사도는 1이기 때문에

65536을 반환하도록 하였다.

 

4. 교집합을 구하기 위해 

str1 요소에 접근하는 반복문 안에 str2요소를 접근하는 반복문을 사용하여 차례로 비교하였다.

 

조건)

1. str1Array[i]와 str2Array[j]가 같아야 함

2. str1Array[i]에 str2Array 요소가 차례로 접근할때 첫번째로 같은 요소여야함

첫번째 같은지를 판단하기 위해 count 변수를 사용함

3. str2Array[j]도 마찬가지로 str1Array의 요소와 차례로 접근할때 전에 이미 같은 요소로 교집합에 추가된 경우에는 추가해주면 안됨

str2Array가 str1Array와 같았을 때 index를 indexArray에 추가하도록 하였고 indexArray에 index를 가지고 있지 않을 경우를 확인함

 

3가지 조건을 모두 만족하는 요소를 intersectionArray에 추가함

 

5. 합집합을 구하기 위해 (두 집합의 합 - 교집합)

unionArray에 str1Array와 str2Array를 더해주었고 교집합 intersectionArray의 요소들을 .remove메서드를 통해 제거함

 

6. 교집합의 개수(intersection), 합집합의 개수(union) 는 Int형의 자료형을 가져 Double형으로 변환 해준 후 자카드 유사도를 구한다. 

정수 부분만 반환해야 하기 때문에 Int(교집합 / 합집합 * 65536) 를 반환하였다. 

 

 

 

func solution(_ str1:String, _ str2:String) -> Int {
    let alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    let str1 = str1.map{String($0)}
    let str2 = str2.map{String($0)}
    
    var str1Array = [String]()
    var str2Array = [String]()
    
    for i in 0..<str1.count-1{
        if alphabet.contains(str1[i].uppercased()) && alphabet.contains(str1[i+1].uppercased()){
            str1Array.append(str1[i].uppercased() + str1[i+1].uppercased())
        }    }
        
    for i in 0..<str2.count-1{
        if alphabet.contains(str2[i].uppercased()) && alphabet.contains(str2[i+1].uppercased()){
            str2Array.append(str2[i].uppercased() + str2[i+1].uppercased())
        }
    }

    if str1Array.sorted(by:<) == str2Array.sorted(by:<) {
        return 65536
    }
    
    var intersectionArray = [String]()
    var indexArray = [Int]()
    
    for i in 0..<str1Array.count{
        var count = 0
        for j in 0..<str2Array.count{
            if str1Array[i] == str2Array[j] && count == 0 && !indexArray.contains(j){
                intersectionArray.append(str1Array[i])
                count += 1
                indexArray.append(j)
            }
        }
    }    
    
    var unionArray = str1Array + str2Array    
    
    for i in 0..<intersectionArray.count{
        if let firstIndex = unionArray.firstIndex(of: intersectionArray[i]){
            unionArray.remove(at: firstIndex)
        }
    }
    
    let intersection = intersectionArray.count
    let union = unionArray.count 
    
    let answer:Double =  Double(intersection) / Double(union) * 65536
    
    return Int(answer)
}