[프로그래머스] 실패율 (2019 KAKAO BLIND RECRUITMENT)
2022. 11. 10. 16:21ㆍ기록/Programmers
- 목차
문제 설명
슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다.
그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다.
원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.
이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다.
역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다.
오렐리를 위해 실패율을 구하는 코드를 완성하라.
- 실패율은 다음과 같이 정의한다.
- 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
전체 스테이지의 개수 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] |
입출력 예 설명
입출력 예 #1
1번 스테이지에는 총 8명의 사용자가 도전했으며, 이 중 1명의 사용자가 아직 클리어하지 못했다.
따라서 1번 스테이지의 실패율은 다음과 같다.
- 1 번 스테이지 실패율 : 1/8
2번 스테이지에는 총 7명의 사용자가 도전했으며, 이 중 3명의 사용자가 아직 클리어하지 못했다.
따라서 2번 스테이지의 실패율은 다음과 같다.
- 2 번 스테이지 실패율 : 3/7
마찬가지로 나머지 스테이지의 실패율은 다음과 같다.
- 3 번 스테이지 실패율 : 2/4
- 4번 스테이지 실패율 : 1/2
- 5번 스테이지 실패율 : 0/1
각 스테이지의 번호를 실패율의 내림차순으로 정렬하면 다음과 같다.
- [3,4,2,1,5]
입출력 예 #2
모든 사용자가 마지막 스테이지에 있으므로 4번 스테이지의 실패율은 1이며 나머지 스테이지의 실패율은 0이다.
- [4,1,2,3]
나의 문제 풀이
function solution(N, stages) {
let answer = [];
let failPer = []; // 실패율 배열
let userNum = 0; // 도전한 사용자 수
let notClear = 0; // 클리어하지 못한 사용자 수
for (let i = 1; i <= N; i++) {
userNum = userNum || stages.length;
notClear = [...stages].filter((item) => item === i).length;
failPer.push({ stage: i, per: notClear / userNum });
answer.push(notClear / userNum);
userNum -= notClear;
}
answer.sort((a, b) => b - a);
for (let i = 0; i < answer.length; i++) {
for (let j = 0; j < failPer.length; j++) {
if (answer[i] === failPer[j].per) {
answer[i] = failPer[j].stage;
failPer.splice(j, 1);
}
}
}
return answer;
}
- 실패율
- 스테이지에 도전했으나 아직 클리어하지 못한 사용자 수 / 스테이지에 도전한 사용자 수
- 1부터 주어진 스테이지 수까지 반복한다. (1~N 단계 스테이지)
- userNum 변수에 값을 할당한다.
- 스테이지에 도전한 사용자 수
- 맨 처음에 userNum 변수 값은 0이기 때문에 주어진 stages 배열의 길이를 넣는다.
- 스테이지에 도전한 사용자 수 (stages) === 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열의 길이
- notClear 변수에 값을 할당한다.
- 스테이지에 도전했으나 아직 클리어하지 못한 사용자 수
- stages 배열에서 현재 스테이지와 같은 번호를 가진 요소만으로 새로운 배열을 만든다.
- failPer 배열에 객체를 할당한다.
- 실패율 배열
- { 현재 스테이지 , 실패율 }
- answer 배열에 현재 스테이지의 실패율을 요소로 넣는다.
- 도전한 사용자 수에서 현재 스테이지를 클리어하지 못한 사용자 수를 뺀다.
- 위 과정을 반복한다.
- answer 배열의 요소들을 내림차순으로 정렬한다.
- 이중 for 문을 반복한다.
- answer 배열의 실패율과 failPer 배열의 객체들 중에서 같은 실패율을 가진 객체를 찾는다.
- answer 배열에 해당 객체의 스테이지 번호를 넣는다.
- failPer 배열에서 해당 객체를 삭제한다.
- for 문 안에서 j가 증가하기 때문에 실패율이 같더라도 작은 번호의 스테이지가 먼저 온다.
- for 문을 빠져나와 answer 배열을 반환한다.
다른 사람의 문제 풀이
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]);
}
- 1부터 주어진 스테이지 번호까지 반복한다.
- stages 배열에서 현재 스테이지 번호보다 크거나 같은 요소만으로 새로운 배열을 만든다.
- 배열의 길이를 reach 변수에 할당한다.
- 스테이지에 도전한 사용자 수
- stages 배열에서 현재 스테이지 번호와 같은 요소만으로 새로운 배열을 만든다.
- 배열의 길이를 curr 변수에 할당한다.
- 스테이지에 도전했으나 아직 클리어하지 못한 사용자 수
- result 배열에 [현재 스테이지 번호, 실패율] 배열을 넣는다.
- result 배열을 실패율을 기준으로 내림차순으로 정렬한다.
- result 배열의 요소를 하나씩 꺼내어 스테이지 번호 요소만으로 구성된 배열을 만들어 반환한다.
function solution(N, stages) {
let ans = [];
for (let i = 1; i <= N; ++i) {
let usersReachedCurrentStage =
stages.reduce((acc, curStage) => acc + ((curStage >= i) ? 1 : 0), 0);
let usersStagnatedCurrentStage =
stages.reduce((acc, curStage) => acc + ((curStage == i) ? 1 : 0), 0);
if (usersReachedCurrentStage === 0) {
ans.push({ 'stage': i, 'failRate': 0 });
continue;
}
ans.push({ 'stage': i, 'failRate': (usersStagnatedCurrentStage / usersReachedCurrentStage) });
}
return ans.sort((a, b) => {
if (a.failRate > b.failRate) return -1;
if (a.failRate < b.failRate) return 1;
return a.stage - b.stage;
}).map(entry => entry.stage);
}
- 1부터 주어진 스테이지 번호까지 반복한다.
- stages 배열의 요소들을 하나씩 꺼낸다.
- 현재 배열의 요소가 현재 스테이지 번호보다 크거나 같으면 1, 아니면 0을 누적한다.
- 스테이지에 도전한 사용자 수 변수에 누적한 값을 할당한다.
- stages 배열의 요소들을 하나씩 꺼낸다.
- 현재 배열의 요소가 현재 스테이지 번호와 같으면 1, 아니면 0을 누적한다.
- 스테이지에 도전했으나 클리어하지 못한 사용자 수 변수에 누적한 값을 할당한다.
- 현재 스테이지에 도전한 사용자가 없다면
- ans 배열에 객체를 할당한다.
- { 현재 스테이지: i, 실패율: 0 }
- ans 배열에 객체를 할당한다.
- { 현재 스테이지: i, 실패율: 스테이지에 도전했으나 클리어하지 못한 사용자 수 / 스테이지에 도전한 사용자 수 }
- ans 배열의 요소를 내림차순으로 정렬한다.
- ans 배열의 요소인 객체를 하나씩 꺼낸다.
- 해당 객체의 stage 프로퍼티만을 요소로 가진 배열을 만들어 반환한다.
function solution(N, stages) {
let stageCount = new Array(N);
let failPer = [];
stageCount.fill(0);
let usersNum = stages.length;
for (let val of stages) {
stageCount[val - 1]++;
}
for (let i = 0; i < N; i++) {
if (usersNum === 0) {
failPer.push({ failper: 0, stageNum: i + 1 });
} else {
failPer.push({ failper: stageCount[i] / usersNum, stageNum: i + 1 });
}
usersNum -= stageCount[i];
}
failPer.sort((a, b) => {
if (a.failper === b.failper) {
return a.stageNum - b.stageNum;
}
return b.failper - a.failper;
});
return failPer.map(item => {
return item.stageNum;
});
}
- 주어진 스테이지 갯수만큼의 길이를 가진 배열을 생성하여 stageCount 변수에 할당한다.
- 해당 배열의 요소를 0으로 채운다.
- userNum 변수에 stages 배열의 길이를 할당한다.
- 스테이지에 도전한 사용자 수
- stages 배열의 요소를 하나씩 꺼낸다.
- stageCount 배열[스테이지 번호 - 1] 의 값을 1씩 증가시킨다.
- 배열의 인덱스는 0부터 시작하기 때문
- stageCount === 스테이지에 도전했으나 클리어하지 못한 사용자 수
- userNum 변수의 값이 0일 경우 failPer 배열에 실패율과 스테이지 번호를 프로퍼티로 가진 객체를 넣는다.
- 도전한 사용자 수에서 현재 스테이지를 클리어하지 못한 사용자 수를 뺀다.
- 위 과정을 스테이지 수 만큼 반복한다.
- 실패율 배열을 내림차순으로 정렬한다.
- 실패율 배열의 요소인 객체를 하나씩 꺼낸다.
- 스테이지 번호만을 요소로 한 새로운 배열을 만들어 반환한다.
function solution(N, stages) {
let answer = [];
let totalUser = stages.length;
for (let i = 1; i <= N; i++) {
let failUser = stages.filter(el => el === i).length;
let fail = 0;
if (failUser === 0) {
fail = 0;
} else {
fail = failUser / totalUser;
}
totalUser -= failUser;
answer.push({ idx: i, ratio: fail });
}
answer.sort((a, b) => {
if (a.ratio === b.ratio) {
return a.idx - b.idx;
} else {
return b.ratio - a.ratio;
}
})
return answer.map(el => el.idx);
}
function solution(N, stages) {
let nums = stages.length;
let count = 0;
let arr = [];
let result = [];
let obj = new Object();
for(let i = 1; i <= N; i++) {
for(let j = 0; j < stages.length; j++) {
if(i === stages[j]) {
count++;
}
}
obj[i] = count / nums;
arr.push([i, obj[i]]);
nums = nums - count;
count = 0;
}
arr.sort((a, b) => { return b[1] - a[1]; })
arr.forEach((key,index) => {
result.push(arr[index][0]);
})
return result;
}