티스토리 뷰

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

 

코딩테스트 연습 - 실패율

실패율 슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스

programmers.co.kr

 

해결방법

1. 1부터 N까지의 숫자 i를 stages의 숫자와 비교해 i보다 크거나 같으면 도전자 +1, 같으면 실패 유저 +1로 카운트

2. 각 스테이지별 실패율 계산하여 all_failure_rate에 저장

3. 스테이지에 도달한 유저가 없는 경우 즉, 도전자가 없는 경우 실패율은 0으로

4. all_failure_rate 에 저장한 실패율의 내림차순으로 스테이지 번호 출력

 

풀이

function solution(N, stages) {
    var answer = [];
    let all_failure_rate = [];
    let max = 0;
    
    for (let i = 1; i < N+1; i++){
        let all_challengers = 0;
        let fail_user = 0;
        let failure_rate = 0;  
        for (let user of stages){
            //총 도전자
            if (user >= i) all_challengers += 1;
            //실패한 유저
            if (user === i) fail_user += 1;
        }
        //실패율
        failure_rate = fail_user / all_challengers;
        // 스테이지에 도달한 유저가 없는 경우 실패율은 0
        if (all_challengers == 0) failure_rate = 0;
        all_failure_rate.push(failure_rate);
    }
    //각 스테이지의 번호를 실패율의 내림차순으로 정렬
    for (let j = 0; j < all_failure_rate.length; j++){
        max = Math.max(...all_failure_rate);
        answer.push(all_failure_rate.indexOf(max)+1);
        all_failure_rate.splice(all_failure_rate.indexOf(max), 1,-1);
    }
    
    return answer;
}

각 스테이지의 번호를 실패율의 내림차순으로 정렬한 answer를 만들 방법을 생각하는데 시간이 좀 걸렸다

내가 생각한 방법은 다음과 같다

 

1. 모든 실패율이 담긴 all_failure_rate에서 최댓값을 찾아 max에 저장

2. all_failure_rate에서 max의 index +1 을 answer에 추가

여기서, 최댓값이 여러개일땐 스테이지 번호가 작은 것이 먼저 와야한다고 문제에 명시되어 있으므로 

처음으로 일치하는 값의 인덱스를 반환하는 indexOf를 사용

3. 그 다음 최댓값을 찾기 위해 위에서 사용한 최댓값을 -1로 바꿈

4. 1~3반복

 

배운 점

1. filter와 map

각 스테이지의 번호를 실패율의 내림차순으로 정렬하는 다른 방법을 알아보고자 다른 분들의 풀이를 보았다

가독성 좋고 내가 짠 코드 길이의 반 밖에 안되는 좋은 코드를 발견했다

function solution(N, stages) {
    let result = [];
    for(let i=1; i<=N; i++){
        let reach = stages.filter(x => x >= i).length;
        let curr = stages.filter(x => x === i).length;
        result.push([i, curr/reach]);
    }
    result.sort((a,b) => b[1] - a[1]);
    return result.map(x => x[0]);
}

이 코드를 보자마자 '맞다 filter가 있었지' 라는 생각이 들었다

나는 for문과 if문을 사용해 총 도전자 수와 실패 유저를 구했는데

이 코드에선 조건을 만족하는 값만 고르는 filter를 이용해 한 줄로 끝냈다

 

또한 각 스테이지의 번호를 실패율의 내림차순으로 정렬하는 방법도 간단했다

1. [스테이지 번호, 실패율]을 짝지어 push하고  // .push([i, curr/reach]);

2. 실패율에 따라 내림차순 정렬을 한 후 // .sort((a,b) => b[1] - a[1]);

3. 스테이지 번호만 뽑아 리턴한다 // .map(x => x[0]);

 

배열 내의 모든 요소 각각에 대해 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환하는 map도

머릿 속에 저장해 놓아야겠다

 

한 번에 이 정도의 코드를 짜려면 난 아직 더 연습이 많이 필요한 것 같다

댓글