코딩테스트

[파이썬(python)] 2022 카카오 블라인드 공채 양궁대회

고후 2022. 3. 9. 18:16

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

 

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

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

programmers.co.kr

가장 문제였던 양궁 문제....

분명 열심히 풀었는데 10개 테스트케이스에서 5개만 통과함.

주어진 테스트1과 테스트3도 통과하지 못했다.

 

조건 하나를 깜빡했다.

어피치와 라이언이 같은 개수의 화살을 맞힌 경우 어피치가 점수를 가져간다.

이 조건을 빼먹음.. 코드 수정하니까 테스트케이스 23번만 통과하지 못했다. 

 

그런데 answer과 real_answer라는 배열을 두개 생성했는데.. 굳이 꼭 두개나 사용할 필요가 있을까? 개선할 필요를 느꼈다.

사실 배열 두개를 사용한 것은 문제에서 '라이언이 가장 큰 점수차로 이기는 경우가 여러개일 경우' 작은 과녁을 여러발 맞힌 것을 정답으로 제출해야 한다는 것을 보고 만든 것이었다. 

 

 

수정 전 코드

 

from itertools import combinations_with_replacement

def solution(n, info):
    answer = []
    real_answer = []
    info.reverse()
    
    if info[10] == n:
        return [-1]
    
    com = combinations_with_replacement([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], n)
    
    result = 0
    
    for c in com:
        ryan = 0
        apeach = 0
        r = [0] * 11
        
        for i in range(n):
            r[c[i]] += 1 
            
        for i in range(11):
            if info[i] == 0 and r[i] == 0:
                continue
            elif r[i] <= info[i]:
                #똑같이 쏘거나 어피치가 더 많이 쏘는 경우
                apeach += i
            else:
                ryan += i
        score = ryan - apeach
        #점수 차이 저장
        if score <= 0:
            continue
            
        if score >= result:
            result = score
            #max 점수 차 저장
            answer.append([r, score])
        
    answer.sort(key = lambda x:-x[1])
    #점수값 높은 순으로 내림차순
    
    max_score = answer[0][1]
    
    
    for i in answer:
        if i[1] == max_score:
            real_answer.append(i[0])
    
    real_answer.sort()
    
    return list(reversed(real_answer[-1]))

 

개선한 코드

중복조합을 생성하는 과정에서 적은 과녁을 많이 쏘는 것부터 조합을 생성하게 된다.

따라서 각 조합마다 저장된 score보다 점수차가 클 때만 answer를 계속 변경해주면 자연히 적은 과녁을 많이 쏘면서, 점수차가 가장 큰 것을 answer로 저장하게된다.

from itertools import combinations_with_replacement

def solution(n, info):
    answer = []
    info.reverse()
    #info[i] = 어피치가 i점을 맞힌 화살 개수
    
    if info[10] == n:
        #10점만 어피치가 n번 쏜 경우 라이언은 절대 이길 수 없음
        return [-1]
    
    score = 0 #라이언과 어피치의 점수차
    
    for c in combinations_with_replacement([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], n):
        ryan = 0
        apeach = 0
        r = [0] * 11
        #r[i] = 라이언이 i점을 맞힌 화살 개수
        
        for i in range(n):
            r[c[i]] += 1 
            
        for i in range(11):
            if info[i] == 0 and r[i] == 0:
                continue
            elif r[i] <= info[i]:
                #똑같이 쏘거나 어피치가 더 많이 쏘는 경우
                apeach += i
            else:
                ryan += i
                
        if score < ryan - apeach:
            answer = r
            #정답에 r 저장
            score = ryan - apeach
            #점수 차이 저장
    
    if score <= 0:
        #라이언이 이기지 않는 경우
        return [-1]
    
    answer.reverse()
    #다시 뒤집어줘야 함
    
    return answer