본문 바로가기
알고리즘

[프로그래머스] Swift - 인사고과

by 바등쪼 2023. 8. 11.

https://school.programmers.co.kr/learn/courses/30/lessons/152995#qna

 

프로그래머스

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

programmers.co.kr

 

2023.08.11 기준 Level 3

 

알고리즘 공부를 위해 풀고 기록하는 글입니다!
참고만 해주시고 더 좋은 풀이법이 있다면 알려주세요!

 

아이디어

  1. 인센티브를 받지 못하는 사람들을 걸러낸다.
  2. 인센티브를 받을 수 있는 명단에서 각 사원의 점수의 합을 구한다.
  3. 이 점수의 합을 내림 차순으로 정렬한다.
  4. 완호의 점수의 위치(index)를 리턴한다.

 

이 흐름으로 구현을 시작했습니다.

 

우선 1번의 작업이 이 문제의 핵심입니다.

 

근무 태도 점수와 동료 평가 점수가 임의의 한 사원보다 모두 작은 사원은 인센티브를 받지 못합니다.

따라서 이런 인원을 찾아야하는데 변수가 근무 태도 점수와 동료 평가 점수로 총 2가지이기 때문에 한가지를 고정시켜야 합니다.

이를 위해 근모 태도 점수를 기준으로 내림차순으로 정렬을 했습니다.

 

이렇게 하면 i번째 사람은 i-1번째 사람보다 근무 태도 점수가 부족한 사람이기 때문에 동료 평가 점수는 무조건 i-1까지의 사람들보다 크거나 같은 경우가 있어야 인센티브를 받을 수 있습니다.

 

즉, 0부터 i-1번째 사람들 중에 동료 평가 점수의 최댓값보다 i번째 사람의 동료 평가 점수가 작다면 근무 태도는 내림차순으로 정렬되어 있기 때문에 인센티브를 받을 수 없다는 의미입니다.

 

하지만 여기서 1가지 더 고려해야할 것이 있습니다. 근무 태도 점수를 기준으로 내림차순을 했더라도 만약 근무 태도가 같은 사람이 있는 상황이 존재하기 때문에 이것을 고려해줘야 합니다.

만약 [5,5], [5,4], [3,5], [3,1], [2,0] 로 정렬된 상태라면 i가 1일 때 [5,4]가 인센티브를 받을 수 있는지 검사합니다. 이 때 이전까지의 동료 평가 최고점은 5입니다. 인덱스 1의 사람은 동료 평가 점수가 4이기 때문에 인센티브를 받을 수 없다고 결정나게 됩니다.

하지만 이것은 오류입니다.

[5,4]보다 두 점수 모두 앞서는 사람이 없기 때문에 인센티브 대상이어야 합니다.

근무 태도 평가 점수가 앞사람과 동률이고 앞의 사람의 동료 평가 점수가 최댓값이었기 때문에 인센티브를 받을 수 없는 사람에 속하지 않게 된 것입니다.

 

즉, 근무태도가 점수가 내림차순이긴 하지만 동률인 경우를 위해 근무 태도가 같은 경우에는 동료 평가 점수를 오름차순으로 정렬해주고 계산을 해야합니다. 이렇게 정렬을 했다면

[5,4], [5,5], [3,1], [3,5], [2,0] 형태가 됩니다.

이러면 [5,4]인 사람보다 [5,5]를 더 늦게 검사하기 때문에 [5,4]도 인센티브 대상에 들어가게 됩니다. (정상적인 계산이 가능해진 것입니다.)

반면 [3,1]인 사람은 이전까지의 동료 평가 최고점 5를 넘지 못했기 때문에 대상에서 제외됩니다. [2,0]도 마찬가지 입니다.

만약 완호의 점수가 제외 대상이라면 -1를 즉시 리턴하면 됩니다.

 

 

이 과정을 통해 인센티브 대상을 다 찾았으면 이제 합산 점수를 기준으로 줄세우면 됩니다.

map을 통해 합산 점수로 배열의 형태를 바꾸고 내림차순으로 정렬합니다.

[5,5,5,4,4,4,3] 이고 4가 완호의 합산 점수라면 4등입니다.

등수를 찾는 방법은 합산 점수 배열에서 완호의 함산 점수가 나오는 첫번째 인덱스에 +1을 하면 됩니다.

 

 

 

풀이

fileprivate func solution(_ scores:[[Int]]) -> Int {
    let target = scores[0] // 완호의 점수
    
    let attitudeScoreAscendingSorted = scores.sorted(by: { $0[0] > $1[0] || ($0[0] == $1[0] && $0[1] < $1[1]) })
    var maxPeerEvaluationScore = attitudeScoreAscendingSorted.first![1]
    
    var peopleCanGetIncentive = [[Int]]()
    
    for score in attitudeScoreAscendingSorted {
        if maxPeerEvaluationScore > score[1] {
            if score == target { return -1 }
            continue
        } else {
            peopleCanGetIncentive.append(score)
        }
        maxPeerEvaluationScore = max(maxPeerEvaluationScore, score[1])
    }
    
    let overallScore = peopleCanGetIncentive.map { $0[0] + $0[1] }.sorted(by: >)

    guard let ranking = overallScore.firstIndex(of: target.reduce(0, +)) else {
        return -1
    }
    
    return ranking + 1
}

attitudeScoreAscendingSorted 배열을 구하는 정렬 조건이 주요했습니다.

근무 태도는 내림차순, 만약 근무 태도가 같은 값이면 동료 평가를 오름차순으로!

 

 

 

마무리

간단한 문제 같았지만 정렬 조건을 잘 설정해야 했습니다.

이렇게 2가지의 변수가 비교 대상이라면 한쪽을 기준점으로 잡고 오름/내림 차순으로 하여 비교 대상에서 제외시키는 방식을 사용해야 한다는 것을 배웠습니다.

댓글