Algorithm Problem Solving/Programmers

[프로그래머스] 2021 KAKAO BLIND RECRUITMENT 메뉴 리뉴얼 with Swift

코코자장자장 2021. 12. 24. 14:52

안녕하세요! 오늘은 프로그래머스 메뉴 리뉴얼 문제를 풀어보겠습니다!

무려 2일이나 걸려서 풀었는데요... 하하... 제 능력의 참담함을 느낍니다...!

 

하지만 문제 푸는 방법을 알고 있다면 금방 푸실 수 있습니다!

 

문제 푸는 흐름에 대해서 설명드리겠습니다!

 

 

1.  orders에서 course로 주어진 문자열 길이와 같은 조합을 모두 구한다.

    - 조합을 구하기 위해서 재귀함수로 이루어진 조합 함수를 구현한다.

    - 인자로는 조합할 재료(order), 조합 결과 담을 배열(combination), 조합 결과(combinationResult), 조합할 결과의 길이(stringSize), 현재 조합할 재료에서 조합중인 위치(startNumber)

    - 재귀함수의 탈출조건으로 현재 조합중인 combinationResult의 길이가 stringSize와 같으면 합 결과 담을 배열(combination)에 넣고 return

    - 이미 조합한 것을 중복으로 넣지 않기 위해 startNumber부터 order의 길이만큼 for문을 반복하면서 재귀시켜줍니다.

    - 재귀함수 전후로 현재 조합중인 combinationResult에 order[startNumber]를 넣어주고 빼어준다.

 

 

2. 조합 내에서 같은 것의 갯수가 2이상이고 최대값인 조합을 answer에 넣어준다. 

    - dictionary를 이용해 조합의 갯수를 찾아준다.

    - 조합 중 중복된 갯수가 2이상이면서 최대값인 조합을 answer에 넣어준다.

 

이런 과정을 거치면 문제가 해결됩니다!

 

import Foundation

func generateCombination(order: [Character], combination: inout [String], 
                         combinationResult: inout String, 
                         stringSize: Int, startNumber: Int) {
    if combinationResult.count == stringSize {
        combination.append(combinationResult)
        return
    }
    for i in startNumber..<order.count {
        combinationResult.append(order[i])
        generateCombination(order: order, combination: &combination, 
                            combinationResult: &combinationResult, 
                            stringSize: stringSize, startNumber: i + 1)
        combinationResult.removeLast()
    }
}

func solution(_ orders:[String], _ course:[Int]) -> [String] {
    let orders = orders.map ({(order: String) -> [String.Element] in 
                              return order.sorted() 
                             })
    var answer : [String] = [String]()
    var combinations: [String] = [String]()
    
    for order in orders {
        for i in course {
            var combination: [String] = []
            var combinationResult: String = ""
            generateCombination(order: order, combination: &combination,
                                combinationResult: &combinationResult, 
                                stringSize: i, startNumber: 0)
            combinations += combination
        }
    }
    
    for i in course {
        var combinationCounts: [String : Int] = [:]
        let combination = combinations.filter({(combination: String) -> Bool in 
                                               return combination.count == i 
                                              })
        for j in combination {
            combinationCounts[j] = combination.filter({(item: String) -> Bool in
                                                       return item == j 
                                                      }).count
        }
        
        let maxCount = combinationCounts.values.max()
        if maxCount == 1 { 
            continue 
        }
        
        combinationCounts.keys.filter({(combination: String) -> Bool in 
                                       return combinationCounts[combination] == maxCount 
                                      }).forEach({(combination: String) -> Void in
            answer.append(combination)
        })
    }
    
    return answer.sorted()
}

 

이번 문제에 고차함수가 많이 나왔는데 다음에는 고차함수에 관한 포스팅도 추가해야겠습니다! 허헣...

 

오늘은 여기까지입니다!

 

감사합니다!

 

 


inout 함수 남발에 고차함수도 너무 많이 써서 다시 좀 간단하게 정리했습니다!

 

import Foundation

var combinations:[String] = [String]()
var combinationResult:String = String()

func generateCombination(order: [Character], stringSize: Int, startNumber: Int) {
    if combinationResult.count == stringSize {
        combinations.append(combinationResult)
        return
    }
    
    for i in startNumber..<order.count {
        combinationResult.append(order[i])
        generateCombination(order: order, 
                         stringSize: stringSize, startNumber: i+1)
        combinationResult.removeLast()
    }
}

func solution(_ orders:[String], _ course:[Int]) -> [String] {
    var answer: [String] = []
    let orders = orders.map({(order: String) -> [String.Element] in 
        return order.sorted()
    })
    
    for order in orders {
        for i in course {
            combinationResult = ""
            generateCombination(order: order, stringSize: i, startNumber: 0)
        }
    }
    
    for i in course {
        var dictionaryCombination:[String : Int] = [String : Int]()
        for combination in combinations {
            if combination.count == i {
                dictionaryCombination[combination] = combinations.filter({(combinations:String) -> Bool in
                                                                     return combinations == combination
                                                                     }).count
            }
        }
        
        let maxCount = dictionaryCombination.values.max()
        if maxCount == 1 || maxCount == nil{
            continue
        }
        answer.append(contentsOf: dictionaryCombination.filter({
            (dictionary:(key: String, value: Int)) -> Bool in
            return dictionary.value == maxCount
        }).keys)
    }
    
    return answer.sorted()
}