🍄 코딩테스트
코딩테스트 문제 풀이
✍🏻 Github
수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 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 함수를 작성해주세요.
제한 조건
입출력 예
answers | return |
---|---|
[1,2,3,4,5] | [1] |
[1,3,2,4,2] | [1,2,3] |
입출력 예 설명
입출력 예 #1
따라서 가장 문제를 많이 맞힌 사람은 수포자 1입니다.
입출력 예 #2
나의 풀이
import Foundation
func solution(_ answers:[Int]) -> [Int] {
// 수포자들의 답안지
let case1 = [1,2,3,4,5]
let case2 = [2,1,2,3,2,4,2,5]
let case3 = [3,3,1,1,2,2,4,4,5,5]
// 맞춘 개수
var answersCount: [Int] = [0,0,0]
for i in 0..<answers.count {
if case1[i%5] == answers[i%answers.count] {
answersCount[0] += 1
}
if case2[i%8] == answers[i%answers.count] {
answersCount[1] += 1
}
if case3[i%10] == answers[i%answers.count] {
answersCount[2] += 1
}
}
return answersCount.enumerated().filter{ $0.element == answersCount.max()! }.map{ $0.offset + 1 }
}
처음에는 문제를 잘 이해하지 못했던 것 같다.
예시와 더불어 반복해서 읽어보니 어떻게 풀어야할지가 보였고,
배열의 나머지 연산을 이용해 반복적인 비교를 하였다.
완전 탐색으로 밖에 풀지 못하는 문제라 더 반복문을 만들려고만 하지 않았다.
맞춘 개수를 처음엔 변수로 나열하다가 마지막에 map을 써서 답을 도출해내고 싶어서 배열을 사용했다.
가장 많이 맞춘 사람의 번호를 출력하는 문제여서 배열의 최댓값을 이용해 가장 많이 맞춘 사람을 도출해냈고,
enumerated를 사용하여 그 사람의 인덱스 번호를 출력하였다.
다른 사람 풀이
import Foundation
func solution(_ answers:[Int]) -> [Int] {
let answer = (
a: [1, 2, 3, 4, 5], // index % 5
b: [2, 1, 2, 3, 2, 4, 2, 5], // index % 8
c: [3, 3, 1, 1, 2, 2, 4, 4, 5, 5] // index % 10
)
var point = [1:0, 2:0, 3:0]
for (i, v) in answers.enumerated() {
if v == answer.a[i % 5] { point[1] = point[1]! + 1 }
if v == answer.b[i % 8] { point[2] = point[2]! + 1 }
if v == answer.c[i % 10] { point[3] = point[3]! + 1 }
}
return point.sorted{ $0.key < $1.key }.filter{ $0.value == point.values.max() }.map{ $0.key }
}
⁉️ 상수 안에 배열을 어떻게 넣을 수 있나?!?
위의 answer은 tuple 타입의 상수이다. 각각의 tuple의 요소에 배열을 넣고, 튜플의 파라미터인 배열에 이름을 붙인 것이다.
학생 수가 3명 밖에 되지 않아서 굳이 Dictionary를 사용해서 풀지 않아도 되겠다고 생각했는데, 사람 수가 많아진다면 이 분의 풀이가 좀 더 유용할 것 같다.
⁉️ 딕셔너리의 값에 + 1 이라는 연산을 할 때, !를 붙여주는 이유는?!?!
딕셔너리는 배열처럼 정해진 범위 안에서의 값이 아니기 때문에, 어떤 키값을 가지고 있는지 알 수가 없다.
애플에서는 딕셔너리에서 없는 키를 호출했을 때의 오류가 날 가능성을 생각하여 딕셔너리의 값을 옵셔널로 감싸두었다.
그래서 딕셔너리에서는 값을 불러올 때는 옵셔널을 한번 벗겨내야한다.
Tuple 이란?
배열과 딕셔너리와는 다르게 여러가지의 타입을 하나의 변수나 상수에 저장할 수 있는 타입이다.
let tuple1 = (0.1, 2, 3, "String")
print(tuple1.0) // 0.1
print(tuple1.1) // 2
print(tuple1.2) // 3
print(tuple1.3) // "String"
let tuple2 = ( a: 0.1, b: 2, c: 3, d: "String")
print(tuple2.a) // 0.1
print(tuple2.b) // 2
print(tuple2.c) // 3
print(tuple2.d) // "String"
print(tuple2.0) // 0.1
var tpl01: (Int, Int) = (100,200)
var tpl02: (Int, String, Int) = (100, "a", 200)
var tpl03: (Int, (String, String)) = (100, ("t", "v"))
var tpl04: (String) = ("sample string")
이 때, tpl04
를 주목해보면 튜플로 선언을 하였더라도 튜플 안의 요소가 1개 밖에 저장되어 있지 않다면, 일반 자료형으로 선언이 된다.
print(type(of: tpl04)) //String
1
은 Int
로 “안녕하세요”
는 String
으로 컴파일러가 자동으로 타입 추론을 하여 타입을 정의내린다.
하지만 0.1
과 같은 값들은 float
도 가능하고 Double
로도 정의가 가능하다. 이럴 땐 더 상위 타입으로 정의가 된다. 그러므로 “a”
는 String
로 정의된다.
타입 어노테이션(Type Annotation) 이란?
자료형을 지정해주는 것이다.
예를 들어var a: Int = 1
와 같이a
라는 변수를 선언할 때: Int
로 이 변수의 타입을 개발자가 지정해주는 것이다.