[프로그래머스] lv1. 실패율

문제
코딩테스트 연습 - 실패율 | 프로그래머스 (programmers.co.kr)
코딩테스트 연습 - 실패율
실패율 슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스
programmers.co.kr
문제설명
슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.
이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.
- 실패율은 다음과 같이 정의한다.
- 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수로 주어질 때, 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수를 완성하라.
제한사항
- 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.
- stages의 길이는 1 이상 200,000 이하이다.
- stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.
- 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.
- 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.
- 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.
- 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.
입출력 예

입출력 예 설명
입출력 예 #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) {
var answer = []
const obj = {}
const 실패율 = {}
let 인원 = 0;
stages.forEach(val => obj[val] = (obj[val] || 0) + 1) // A파트
for (let i = 1; i <= N; i++) { // B파트
if (!obj[i]) 실패율[i] = 0
else {
실패율[i] = obj[i] / (stages.length - 인원)
인원 = 인원 + obj[i]
}
}
let sorted = Object.entries(실패율).sort((a, b) => b[1] - a[1]) // C파트
for (let x of sorted) answer.push(+x[0]) // D파트
return answer;
}
solution(5, [2,1,2,6,2,4,3,3]) // [3,4,2,1,5]
solution(4, [4,4,4,4,4]) // [4,1,2,3]
풀이
A파트
- solution 함수의 인자로 들어온 stages 배열변수의 중복 값 개수를 구해서 새로운 객체변수에 담아놓는다.
const obj = {}
stages.forEach(val => obj[val] = (obj[val] || 0) + 1)
console.log(obj) // {1: 1, 2: 3, 3: 2, 4: 1, 6: 1}
B파트
- A파트에서 만든 obj 값을 이용해서 실패율 객체를 최신화한다.
1️⃣ 반복문은 1부터 solution 첫 번째인자 값인 N까지 돌려준다. (1단계부터 N단계 까지 실패율을 알아야 하기 때문)
2️⃣ A파트에서 구한 obj[i]값이 없으면(undefined이면) 실패율이 0%이라는 말이다.
3️⃣ obj[i]값이 있다면, 단계별 실패율을 객체변수에 넣어준다.
분모에 앞 스테이지를 클리어한 인원을 뺀 값을 넣는다.
4️⃣ 스테이지를 클리어한 인원을 최신화(누적) 해준다.
(1단계를 클리어했으면 +1, 2단계를 클리어했으면 +1+3, 3단계를 클리어하면 +1+3+2 ...)
const 실패율 = {}
let 인원 = 0;
for (let i = 1; i <= N; i++) { // 1️⃣
if (!obj[i]) 실패율[i] = 0 // 2️⃣
else { // 3️⃣
실패율[i] = obj[i] / (stages.length - 인원)
인원 = 인원 + obj[i] // 4️⃣
}
}
console.log(실패율) // {1: 0.125, 2: 0.42857142857142855, 3: 0.5, 4: 0.5, 5: 0}
C파트
- 객체인 실패율 변수를 value값을 기준으로 하는 내림차순 배열을 만든다.
let sorted = Object.entries(실패율).sort((a, b) => b[1] - a[1])
console.log(sorted)
//(5) [Array(2), Array(2), Array(2), Array(2), Array(2)]
//0: (2) ['3', 0.5]
//1: (2) ['4', 0.5]
//2: (2) ['2', 0.42857142857142855]
//3: (2) ['1', 0.125]
//4: (2) ['5', 0]
D파트
- C파트에서 내림차순된 배열변수에서 첫 번째 인자만 따로 answer 변수에 push 해준다.
for (let x of sorted) answer.push(+x[0])
return answer; // (5) [3, 4, 2, 1, 5]
느낀점
문제 풀이방식에 접근하기 위해서 아래 2가지를 활용했다.
1. 배열의 중복된 값의 개수를 구하기
2.Object의 value 값을 기준으로 간단하게 새 배열에 정렬해 넣기
처음에는 문제풀이를 어떻게 할까 고민하다가 위의 2가지 방식을 떠올리게 되었다.
구글에 서치한 후 문제풀이에 적용하니 문제를 해결할 수 있었다.
내가 푼 방식이 효율적이거나 정확한 방식은 아닐지 모르지만, 스스로 문제를 푼것에 대해서 만족감을 느낀다.
아래 참고 링크를 재방문해서 꼭 복습하길..
참고
[Javascript] 배열 중복 값 개수 구하기 - 어제 오늘 내일 (tistory.com)
[Javascript] 배열 중복 값 개수 구하기
배열에 있는 값들이 몇번이나 중복 되는지 찾는 방법을 소개합니다. forEach() 이용하기 reduce() 이용하기 Map 객체 이용하기 1. forEach() 이용하기 const arr = ['a', 'b', 'a', 'b', 'c']; const result = {};..
hianna.tistory.com
[Javascript] Object를 value 값으로 간단하게 정렬해보기 (tistory.com)
[Javascript] Object를 value 값으로 간단하게 정렬해보기
Javascript는 Object에 대해서는 따로 sorting method를 지원하지 않는다. 따라서 몇 개의 단계를 거쳐서 sorting을 진행해야 되는데, 찾아본 여러 방법 중에 가장 간단한 코드를 들고왔다. var keywordCount = {..
sophuu.tistory.com