https://school.programmers.co.kr/learn/courses/30/lessons/42889
문제 설명
실패율
슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.
이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.
- 실패율은 다음과 같이 정의한다.
- 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
전체 스테이지의 개수 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]
풀이
전체 스테이지 수(N)만큼만 return array 크기를 맞추면 되고,
- 1보다 크거나 같은 사용자는 총 8명, 1스테이지를 통과하지 못한 사용자 1명
- 2보다 크거나 같은 사용자는 총 7명, 2스테이지를 통과하지 못한 사용자 3명
이런식으로 실패율을 구하기위해 필요한 수를 구할 것이다.
각 사용자가 도전 중인 스테이지가 1...N.count 안에 있으면 해당 스테이지를 통과하지 못한 것이므로 fail에 통과하지 못한 사용자를 카운트 하고,
전체 사용자에서 통과하지 못한 사용자 만큼 빼준 후 통과하지 못한 사용자 수로 나누어준다.(=실패율)
실패율이 높은 순으로 return해주면 됨
코드
// try 1
func solution(_ N:Int, _ stages:[Int]) -> [Int] {
var failPercent = [Int: Double]()
for stage in 1...N {
let player = stages.filter{stage <= $0}.count
let fail = stages.filter{stage == $0}.count
failPercent[stage] = Double(fail) / Double(player)
}
let result = failPercent.sorted(by: <).sorted(by: {$0.value > $1.value})
return result.map{$0.key}
}
// try 2
func solution(_ N:Int, _ stages:[Int]) -> [Int] {
var failPercent = [Int: Double]()
var player = 0
var fail = 0
for stage in 1...N {
for i in stages {
if i >= stage {
player += 1
}
if i == stage {
fail += 1
}
}
failPercent[stage] = Double(fail) / Double(player)
player = 0
fail = 0
}
let result = failPercent.sorted(by: <).sorted(by: {$0.value > $1.value})
return result.map{$0.key}
}
// try 3
func solution(_ N:Int, _ stages:[Int]) -> [Int] {
var failPercent = [(Int, Double)]()
var player = 0
var fail = 0
for stage in 1...N {
for i in stages {
if i >= stage {
player += 1
}
if i == stage {
fail += 1
}
}
failPercent.append((stage,Double(fail) / Double(player)))
player = 0
fail = 0
}
let result = failPercent.sorted(by: <).sorted(by: {$0.1 > $1.1})
return result.map{$0.0}
}
// try 4
func solution(_ N:Int, _ stages:[Int]) -> [Int] {
var failPercent = [(Int, Double)]()
var player = stages.count
for stage in 1...N {
var fail = 0
for i in stages {
if i == stage {
fail += 1
}
}
player -= fail
failPercent.append((stage, Double(fail) / Double(player)))
}
failPercent = failPercent.sorted(by: {$0.1 > $1.1 })
return failPercent.map{$0.0}
}
실패이유
- 딕셔너리 보다 튜플의 속도가 빠르다
이유, 튜플은 최대 크기가 정해져 있는 반면 딕셔너리는 사용자가 원하는 만큼 크기가 늘어날 수 있고
확실한 이유가 될지는 모르겠으나 딕셔너리의 key가 heap 영역에 저장되는 반면 튜플은 stack에 저장된다. - (이 부분은 좀 더 정확한 공부 필요!) - filter보다 for문을 이용하면 복잡도가 줄어든다
그래서 tuple과 for문을 이용해서 수정을 했으나 12번 문제에서 런타임 에러가 발생했다.
func solution(_ N:Int, _ stages:[Int]) -> [Int] {
var failPercent = [(Int, Double)]()
var player = stages.count
for stage in 1...N {
var fail = 0
for i in 0 ..< stages.count {
if stages[i] == stage {
fail += 1
}
}
player -= fail
failPercent.append((stage, Double(fail) / Double(player)))
}
failPercent = failPercent.sorted(by: {$0.1 > $1.1 })
return failPercent.map{$0.0}
}
두번째 for문에 sequence를 그냥 stage
에서 0..<stages.count
로 변경하니 통과가 됐는데 이 이유는 잘 모르겠심! 공부해야겠음
쉬운듯 어려웠다...
정답은 https://rldd.tistory.com/322 여기 참고
자료형에 대해서는
https://coding-sojin2.tistory.com/3
https://devsrkim.tistory.com/entry/Swift-Array-Dictionary-Set-Tuple
참고
'알고리즘 > 프로그래머스' 카테고리의 다른 글
프로그래머스: 월간 코드 챌린지 시즌1 - 3진법 뒤집기 (0) | 2022.08.02 |
---|---|
프로그래머스: 월간 코드 챌린지 시즌2 - 약수의 개수와 덧셈 (0) | 2022.08.02 |
프로그래머스: 월간 코드 챌린지 시즌1 - 내적 (0) | 2022.07.29 |
프로그래머스: 월간 코드 챌린지 시즌2 - 음양 더하기 (0) | 2022.07.28 |
프로그래머스: 2019 카카오 개발자 겨울 인턴십 - 크레인 인형뽑기 게임 (0) | 2022.07.28 |
댓글