1. 문제
슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.
이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.
- 실패율은 다음과 같이 정의한다.
- 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수로 주어질 때, 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수를 완성하라.
제한사항
- 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.
- stages의 길이는 1 이상 200,000 이하이다.
- stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.
- 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.
- 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.
- 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.
- 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.
입출력 예
N | stages | result |
5 | [2, 1, 2, 6, 2, 4, 3, 3] | [3,4,2,1,5] |
4 | [4,4,4,4,4] | [4,1,2,3] |
2. 나의 풀이
function solution(N, stages) {
let answer = [];
// 스테이지 수(분모값)
let completeNum = stages.length
// 스테이지는 1부터 있기 때문에, i = 1 시작, 스테이지는 N + 1까지 있으나, N + 1의 경우에는 마지막까지 완료한 사람이다.
// N까지 반복
for(let i = 1; i <= N; i ++) {
let failRatio;
let failureNum = stages.filter((el) => el === i).length;
if(failureNum === 0) {
failRatio = 0
} else {
failRatio = failureNum / completeNum
}
// 다음 분모로 사용하기 위해
completeNum -= failureNum
answer.push({ key: i, ratio : failRatio})
}
// 1/8 2/4
answer.sort((a, b) => {
// 실패율이 작은게 뒤로
if (a.ratio < b.ratio) {
return 1;
// 실패율이 큰게 앞으로
} else if (a.ratio > b.ratio) {
return -1;
// 실패율이 같다면 key값이 작은게 앞으로(오름차순)
} else {
if(a.key > b.key) {
return 1;
} else {
return -1;
}
}
})
// 배열안에 있는 키값을 가져온다.
return answer.map(el => el.key)
}
문제와 입출력 예시를 보고 생각했다.
- N은 스테이지 갯수, stages에서는 N + 1까지 나온다.
- 각각의 스테이지의 실패율이 높은 순서대로 정렬 되야 한다. 만약 실패율이 동일하다면, 앞선 스테이지 번호가 먼저 나온다.
- 입출력 예시1을 정렬해서 보면 [1, 2, 2, 2, 3, 3, 4, 6] 이다.
- 1단계의 실패율은 1(1단계를 깨지 못한 배열길이) / 총 배열의 길이이다 즉 1/8이다.
- 2단계의 실패율은 1단계를 깨지 못한 사람을 제외하고 계산한다. 실패율은 3 / 총배열에서 이전스테이지를 깨지 못한 배열의 길이,즉 3 / 7 이다.
- 각각 계산해보면 3단계는 2 / 4 4단계는 1 / 2 5단계는 실패한 사람이 없기 떄문에 0이다.
- 6단계 (N + 1)은 마지막 스테이지까지 클리어한 사용자 이다. 즉 실패하지 않았기 떄문에 실패율에 들어가지 않는다.
어려웠던 점은 반복문의 횟수를 정해주는 것과, 객체를 제대로 만들어 주는 것 그리고, 객체의 값을 비교할 때, 각각의 키값을 제대로 활용하지 않아서 틀렸다. 마지막으로 배열안에 있는 키값을 가져오는 것도 생각이 많았다. 배열을 순회해서 각 객체의 키만 가져오는 것을 구구절절 쓰자니..... 으엑 그래서 지난번 풀었던 문제들을 다시 보면서 map을 활용하기로 했다.
[
{key: 3, ratio: 0.5},
{key: 4, ratio: 0.5},
{key: 2, ratio: 0.42857142857142855}, // 대충 3/7인 것...
{key: 1, ratio: 0.125},
{key: 5, ratio: 0}
]
입출력 예시 1번을 정렬까지 마치면 이렇게 정리가 된다. 이때 map을 써서 각각의 key값만 남도록 했다.
으... 어렵다 어려워....
'리코딩 : 알고리즘' 카테고리의 다른 글
6. 프로그래머스 - 나누어 떨어지는 숫자 배열 (0) | 2021.09.16 |
---|---|
5. 프로그래머스 - 3진법뒤집기 (0) | 2021.09.15 |
3. 프로그래머스 - 기능개발 (0) | 2021.09.13 |
2. 프로그래머스 - K번째 수 (0) | 2021.09.11 |
1. 프로그래머스 - 행렬의 덧셈 (0) | 2021.08.26 |