알고리즘/알고리즘 문제풀이

카카오_프로그래머스_양궁대회 swift

Downey 2022. 2. 28. 17:28

https://programmers.co.kr/learn/courses/30/lessons/92342

 

코딩테스트 연습 - 양궁대회

문제 설명 카카오배 양궁대회가 열렸습니다. 라이언은 저번 카카오배 양궁대회 우승자이고 이번 대회에도 결승전까지 올라왔습니다. 결승전 상대는 어피치입니다. 카카오배 양궁대회 운영위원

programmers.co.kr

 

접근 방법

  1. dfs를 사용해서 라이언이 이기거나 지는 모든 경우의 수를 끌어모은다..! 이 때, 어피치보다 점수가 낮은 경우 제외
  2. 끌어 모은 점수 중 라이언의 점수가 max인 경우를 모두 수집한다.
  3. 작은 점수가 많은 경우 순으로 정렬한다.

오답 코드

더보기
import Foundation


    
    func sumScore(scores: [Int]) -> Int {
        var sum = 0
        scores.enumerated().forEach( { (n,c) in
            if c != 0 {
                sum += 10 - n
            }
        })
        
        return sum
    }
    
    func solution(_ n:Int, _ info:[Int]) -> [Int] {
        
        let apchScore = sumScore(scores: info)
        let result = recursion(i: 0, remainShoot: n, ryanInfo: [Int].init(repeating: 0, count: 11), apchInfo: info, apchScore: apchScore)
        let test = Array(result)
        
        var maxRyanScore = 0
        var maxIndexes: [Int] = []
        test.enumerated().forEach({ (n,c) in
            let score = sumScore(scores: c)
            if score > maxRyanScore {
                maxRyanScore = score
                maxIndexes = [n]
            } else if score == maxRyanScore {
                maxIndexes.append(n)
            }
        })
        
//        for i in maxIndexes {
//            print("index: \(i), \(test[i])")
//        }
        
        if maxIndexes.count > 2 {
            var list = [[Int]].init()
            for i in maxIndexes {
                list.append(test[i])
            }
            list.sort(by: {
                for i in stride(from: 10, to: 0, by: -1) {
                    if $0[i] < $1[i] {
                        return false
                    }
                }
                return true
            })
            
            return list.first!
        }
        
        if maxIndexes.isEmpty {
            return [-1]
        }
        
        return test[maxIndexes.first!]
    }
    
    func recursion(i: Int, remainShoot: Int, ryanInfo: [Int], apchInfo: [Int], apchScore: Int) -> Set<[Int]> {
        var sol = Set<[Int]>.init()
        
        var newRyanInfo = ryanInfo
        var newRemainShoot = remainShoot
        var newApchScore = apchScore
        
        if remainShoot <= 0 {
            let ryanScore = sumScore(scores: newRyanInfo)
            if ryanScore > apchScore {
                sol.insert(newRyanInfo)
                return sol
            } else {
                return [[-1]]
            }
        }
        
        if i > 10 {
            let ryanScore = sumScore(scores: newRyanInfo)
            if ryanScore > apchScore {
                sol.insert(newRyanInfo)
                return sol
            } else {
                return [[-1]]
            }
        }
        
        let winOrLose = [false, true] // Ryan기준
        
        for isWin in winOrLose {
            if isWin && remainShoot > apchInfo[i] {
                newRyanInfo[i] = apchInfo[i] + 1
                newRemainShoot -= newRyanInfo[i]
                newApchScore -= 10 - i
                let result = recursion(i: i+1, remainShoot: newRemainShoot, ryanInfo: newRyanInfo, apchInfo: apchInfo, apchScore: newApchScore)
                sol = sol.union(result)
            } else {
                let result = recursion(i: i+1, remainShoot: newRemainShoot, ryanInfo: newRyanInfo, apchInfo: apchInfo, apchScore: newApchScore)
                sol = sol.union(result)
            }
        }
        
        
        return sol
    }

제출 결과

더보기
테스트 1 실패 (1.17ms, 16.5MB)
테스트 2 실패 (16.58ms, 16.4MB)
테스트 3 실패 (15.84ms, 16.4MB)
테스트 4 실패 (8.30ms, 16.5MB)
테스트 5 실패 (13.33ms, 16.7MB)
테스트 6 실패 (14.94ms, 16.4MB)
테스트 7 실패 (4.18ms, 16.6MB)
테스트 8 통과 (3.12ms, 16.4MB)
테스트 9 실패 (6.37ms, 16.4MB)
테스트 10 실패 (5.28ms, 16.4MB)
테스트 11 실패 (5.49ms, 16.3MB)
테스트 12 실패 (4.57ms, 16.4MB)
테스트 13 실패 (11.05ms, 16.5MB)
테스트 14 실패 (7.22ms, 16.6MB)
테스트 15 실패 (11.26ms, 16.5MB)
테스트 16 실패 (5.77ms, 16.6MB)
테스트 17 실패 (6.68ms, 16.3MB)
테스트 18 통과 (1.11ms, 16.4MB)
테스트 19 통과 (0.50ms, 16.5MB)
테스트 20 통과 (14.40ms, 16.6MB)
테스트 21 실패 (16.54ms, 16.4MB)
테스트 22 통과 (13.68ms, 16.5MB)
테스트 23 실패 (1.04ms, 16.3MB)
테스트 24 실패 (23.10ms, 16.6MB)
테스트 25 실패 (21.34ms, 16.6MB)

반성 및 개선 방향

  1. 라이언의 점수가 가장 클 경우, 둘의 점수차가 제일 클 것이라고 예상하였으나, 아닌 경우가 있을 수도 있다는 생각이..
  2. 테스트 케이스를 통과 못하는 경우가 있었다, 이 경우, 화살을 전부 사용하지 않았다. 아마 종료 구문 중, 10번째 과녁까지 간 경우일 것이라고 예상하는데, 이 때 남은 화살을 처리하는 내용이 없기 때문이라고 예상.
  3. 타인의 코드 중 가장 괜찮아 보인것은, 이기고 지는 완전 탐색이 아니라, 화살을 쏘는 모든 경우의 수를 탐색하는 경우였다. 참조 링크 : https://velog.io/@qodlstjd12/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-Kakao-%EC%96%91%EA%B6%81-%EB%8C%80%ED%9A%8C-Java