모의고사
문제 설명
수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.
1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...
1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.
제한조건
시험은 최대 10,000 문제로 구성되어있습니다.
문제의 정답은 1, 2, 3, 4, 5중 하나입니다.
가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.
방법
func topStudentIs(_ answers: [Int]) -> [String] {
let pikachu = [1, 2, 3, 4, 5]
let charmander = [2, 1, 2, 3, 2, 4, 2, 5]
let squirtle = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5]
var score = [String:Int]()
for i in 0..<answers.count {
if answers[i] == pikachu[i%pikachu.count] { score["피카츄"] = ( score["피카츄"] ?? 0 ) + 1 }
if answers[i] == charmander[i%charmander.count] { score["파이리"] = ( score["파이리"] ?? 0 ) + 1 }
if answers[i] == squirtle[i%squirtle.count] { score["꼬부기"] = ( score["꼬부기"] ?? 0 ) + 1 }
}
return score.filter { $0.value == score.values.max() }.keys.sorted()
}
이해하기 쉽게 1번, 2번, 3번 수험생 이름을 각각 피카츄, 파이리, 꼬부기로 지어줬습니다.
정답이 적힌 정수 배열을 파라미터로 전달받으면, 문제를 가장 많이 맞춘 수험생 이름을 배열에 담아 리턴하는 함수를 만들었습니다.
각 수험생들이 찍은 정답은, 반복적인 패턴을 가지고 있어서 정수형 배열로 만들어 줬습니다.
다음 score라는 이름의 빈 딕셔너리를 생성해두고,
for-in반복문으로 문제 갯수 만큼(정답의 갯수 만큼) 반복하도록 범위를 지정해 뒀습니다.
index는 0부터 시작하기 때문에 0..<answers.count로 마지막 범위는 포함시키지 않도록 범위를 지정해서 문제 갯수와 맞춰줬습니다.
반복문 내부에서, 채점을 시작합니다.
만약, [i]번째 정답이 피카츄가 찍은 [i]번째 정답과 일치하는 경우, if블록이 실행됩니다.
score["피카츄"] = ( score["피카츄"] ?? 0 ) + 1
score["피카츄"]처럼 딕셔너리에서 서브스크립트 문법으로 key를 전달하면, "피카츄"key와 연관된 값에 접근할 수 있습니다. 키와 연관된 값은 없을수도 있기 때문에(nil) 형식은 Optional입니다.
그래서 딕셔너리에 저장된 Value값을 사용하려면 언래핑을 해주어야 합니다.
Nil-Coalescing Operator를 사용해, 값이 저장되어 있다면 왼쪽 값을 언래핑해 리턴하고, 값이 nil일 경우 0을 리턴한다음, 마지막에 +1을 더해줬습니다.
위처럼 키와 연관된 값이 없다면 값을 Insert, 값이 있다면 새로운 값으로 Update 하기 때문에 Upsert라는 표현을 사용하기도 합니다.
채점을 마치면, 가장 점수가 높은 수험생을 문자열 배열에 담아 리턴해주면됩니다.
score.filter { $0.value == score.values.max() }.keys.sorted()
동점자가 있는 경우도 있기 때문에, .max() method를 사용해 정답을 가장 많이 맞춘 수험생(=value가 최대값인 요소)만 남도록 .filter method로 걸러준 다음, .keys 속성으로 key값만 따로 뺀 다음, 배열로 정렬된 값을 리턴해줬습니다.