
숫자나라 기사단의 각 기사에게는 1번부터 number까지 번호가 지정되어 있습니다. 기사들은 무기점에서 무기를 구매하려고 합니다.
각 기사는 자신의 기사 번호의 약수 개수에 해당하는 공격력을 가진 무기를 구매하려 합니다. 단, 이웃나라와의 협약에 의해 공격력의 제한수치를 정하고, 제한수치보다 큰 공격력을 가진 무기를 구매해야 하는 기사는 협약기관에서 정한 공격력을 가지는 무기를 구매해야 합니다.
예를 들어, 15번으로 지정된 기사단원은 15의 약수가 1, 3, 5, 15로 4개 이므로, 공격력이 4인 무기를 구매합니다. 만약, 이웃나라와의 협약으로 정해진 공격력의 제한수치가 3이고 제한수치를 초과한 기사가 사용할 무기의 공격력이 2라면, 15번으로 지정된 기사단원은 무기점에서 공격력이 2인 무기를 구매합니다. 무기를 만들 때, 무기의 공격력 1당 1kg의 철이 필요합니다. 그래서 무기점에서 무기를 모두 만들기 위해 필요한 철의 무게를 미리 계산하려 합니다.
기사단원의 수를 나타내는 정수 number와 이웃나라와 협약으로 정해진 공격력의 제한수치를 나타내는 정수 limit와 제한수치를 초과한 기사가 사용할 무기의 공격력을 나타내는 정수 power가 주어졌을 때, 무기점의 주인이 무기를 모두 만들기 위해 필요한 철의 무게를 return 하는 solution 함수를 완성하시오.
number ≤ 100,000limit ≤ 100power ≤ limit| number | limit | power | result |
|---|---|---|---|
| 5 | 3 | 2 | 10 |
| 10 | 3 | 2 | 21 |
입출력 예 #1
1부터 5까지의 약수의 개수는 순서대로 [1, 2, 2, 3, 2]개입니다. 모두 공격력 제한 수치인 3을 넘지 않기 때문에 필요한 철의 무게는 해당 수들의 합인 10이 됩니다. 따라서 10을 return 합니다.
입출력 예 #2
1부터 10까지의 약수의 개수는 순서대로 [1, 2, 2, 3, 2, 4, 2, 4, 3, 4]개입니다. 공격력의 제한수치가 3이기 때문에, 6, 8, 10번 기사는 공격력이 2인 무기를 구매합니다. 따라서 해당 수들의 합인 21을 return 합니다.
import Foundation
func solution(_ number:Int, _ limit:Int, _ power:Int) -> Int {
return (1...number).map{ n in
let k = (1...n).filter{ n%$0 == 0 }.count
return k <= limit ? k : power
}.reduce(0, +)
}
반복문을 돌며, 나누었을 때 0이 되는 횟수로 약수의 개수를 구하려고 시도했지만, 시간 초과 에러가 났다.
테스트 1 〉 실패 (시간 초과)
테스트 2 〉 통과 (1547.01ms, 16.5MB)
테스트 3 〉 통과 (395.24ms, 16.6MB)
테스트 4 〉 통과 (2461.15ms, 16.4MB)
테스트 5 〉 통과 (259.00ms, 16.3MB)
테스트 6 〉 실패 (시간 초과)
테스트 7 〉 통과 (1693.65ms, 16.4MB)
테스트 8 〉 통과 (995.77ms, 16.6MB)
테스트 9 〉 실패 (시간 초과)
테스트 10 〉 통과 (458.95ms, 16.4MB)
테스트 11 〉 실패 (시간 초과)
테스트 12 〉 실패 (시간 초과)
테스트 13 〉 실패 (시간 초과)
테스트 14 〉 실패 (시간 초과)
테스트 15 〉 실패 (시간 초과)
테스트 16 〉 실패 (시간 초과)
테스트 17 〉 통과 (0.15ms, 16.5MB)
테스트 18 〉 실패 (시간 초과)
테스트 19 〉 통과 (1719.36ms, 16.3MB)
테스트 20 〉 통과 (1627.43ms, 16.3MB)
테스트 21 〉 통과 (0.10ms, 16.4MB)
테스트 22 〉 통과 (0.11ms, 16.6MB)
테스트 23 〉 통과 (0.17ms, 16.3MB)
테스트 24 〉 실패 (시간 초과)
테스트 25 〉 실패 (시간 초과)
테스트 26 〉 통과 (204.00ms, 16.6MB)
테스트 27 〉 통과 (210.01ms, 16.5MB)
처참…
약수의 개수를 다른 방법으로 구하는 방법을 생각해내지 못하여 구글링하였다.
function countDivisors(n) {
let cnt = 0;
for (let i = 1; i <= n**(1/2); i++) {
if (n % i === 0) {
if (n / i === i) {
cnt++;
} else {
cnt = cnt + 2;
}
}
}
return cnt;
}
[출처] [JS] 약수의 개수 구하기, reduce()|작성자 연어코
이 분은 JS의 언어로 푼 숫자의 제곱근을 하여 약수의 짝을 고려하는 방식으로 풀었다.
예를 들어,
100의 약수를 구하면 1, 2, 4, 5, 10, 20, 25, 50, 100이다.
100의 제곱근인 10이 100의 약수의 중심이 되어 양쪽을 대칭을 이루는 것을 확인할 수 있다.
굳이 1부터 100까지를 다 비교하는 것이 아니라
1부터 10까지만 나누어 나머지가 0이 된다면
10을 제외한 나머지의 약수들은 2번 더하여 약수의 개수를 찾는 것이다.
한가지 더 예를 들자면,
42의 약수를 구하면 1, 2, 3, 6, 7, 14, 21, 42 이다.
제곱근 42는 6보다는 크고, 7보다는 작기때문에
1부터 6까지를 42로 나누어 약수를 확인한다.
1, 2, 3, 6로 약수가 4개가 나오게 될 것이다.
제곱근 42가 제곱수가 아니므로, 약수의 개수는 8개이다.
이 개념을 바탕으로 약수의 개수를 짜는 코드를 짜면 다음과 같다.
var c = 0
for i in (1...Int(sqrt(Double(number)))) {
if number % i == 0 {
c += (i * i == number ? 1 : 2)
}
}
더 간략히 나타내면
(1...Int(sqrt(Double(number)))).map{ number%$0 == 0 ? ( $0 * $0 == number ? 1 : 2 ) : 0 }.reduce(0, +)
적용하여 문제를 풀면 다음과 같다.
import Foundation
func solution(_ number:Int, _ limit:Int, _ power:Int) -> Int {
var answer = 0
for n in (1...number) {
var c = 0
for i in (1...Int(sqrt(Double(n)))) {
if n % i == 0 {
c += ( i * i == n ? 1 : 2 )
}
}
answer += ( c <= limit ? c : power )
}
return answer
}
테스트 1 〉 통과 (10.19ms, 16.2MB)
테스트 2 〉 통과 (1.33ms, 16.2MB)
테스트 3 〉 통과 (0.49ms, 16.2MB)
테스트 4 〉 통과 (1.79ms, 16.1MB)
테스트 5 〉 통과 (0.38ms, 16.5MB)
테스트 6 〉 통과 (14.37ms, 16.4MB)
테스트 7 〉 통과 (1.52ms, 16.3MB)
테스트 8 〉 통과 (0.85ms, 16.4MB)
테스트 9 〉 통과 (9.65ms, 16.6MB)
테스트 10 〉 통과 (0.59ms, 16.2MB)
테스트 11 〉 통과 (254.36ms, 16.4MB)
테스트 12 〉 통과 (288.65ms, 16.4MB)
테스트 13 〉 통과 (245.61ms, 16.3MB)
테스트 14 〉 통과 (268.80ms, 16.2MB)
테스트 15 〉 통과 (265.02ms, 16.4MB)
테스트 16 〉 통과 (289.52ms, 16.3MB)
테스트 17 〉 통과 (0.01ms, 16.4MB)
테스트 18 〉 통과 (301.43ms, 16.4MB)
테스트 19 〉 통과 (1.29ms, 16.4MB)
테스트 20 〉 통과 (1.32ms, 16.6MB)
테스트 21 〉 통과 (0.01ms, 16.2MB)
테스트 22 〉 통과 (0.01ms, 16.5MB)
테스트 23 〉 통과 (0.01ms, 16.3MB)
테스트 24 〉 통과 (303.41ms, 16.4MB)
테스트 25 〉 통과 (289.43ms, 16.3MB)
테스트 26 〉 통과 (0.35ms, 16.4MB)
테스트 27 〉 통과 (0.31ms, 16.2MB)
실행 시간도 확연히 달라진 것을 확인할 수 있다.
2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각 SUN,MON,TUE,WED,THU,FRI,SAT
입니다. 예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 "TUE"를 반환하세요.
| a | b | result |
|---|---|---|
| 5 | 24 | "TUE" |
func solution(_ a:Int, _ b:Int) -> String {
let week = ["THU","FRI","SAT","SUN","MON","TUE","WED"]
let day = [0,31,29,31,30,31,30,31,31,30,31,30,31]
return week[ ( (0..<a).reduce(0) { $0 + day[$1] } + b ) % 7 ]
}
꽤나 오랜 시간에 걸쳐서 풀려고 노력해보았으나 도저히 3, 9, 11, 14의 런타임 오류는 해결하지 못하였다.
이 문제만 4시간정도 잡고 있었는데..
이렇게도 접근해보고 저렇게도 접근해보았지만,
처음 푼 것 보다 정확도가 더 떨어져서 나올뿐이었다.
원래 하려던 공부를 제치고 꼭 풀어내겠다는 생각으로 달려들었는데 아직 많이 부족한거 같다.
내일 다시 풀어봐야지...
오늘은 TableView와 ScrollView에 대해서 공부했다.
TableView는 ScrollView의 프로토콜을 채택하기 때문에,
TableView안에서 cell이나 스택뷰를 사용하여 ContentView를 구현하였을 때
해당 Content가 화면을 넘어간다면, 자동으로 스크롤이 되는 View로 바뀌게 된다.
TableView의 오토레이아웃을 잡는 방법을 생각보다 복잡했다.
조금이라도 잘 못 적용을 하면,
오류가 나는데 그 오류가 어디서 난지 잘 몰라서
처음부터 다시 오토레아웃을 잡는 것을 반복했다.
오늘 배운 AutoLayout은 따로 정리해두는 걸로..
최근들어 Xcode에서 Simulation을 킬 때마다 너무 느려서 답답해 미치겠다는 느낌을 받았다.
컴파일할 때마다 렉이 걸리는 느낌..ㅠㅜ
그래도 그냥 애써 무시하고 컴파일 돌렸었다.
근데 오늘은 오토레이아웃을 연습한 프로젝트를 실행했하니 main 스토리 보드가 까맣게 보이고, 내가 잡아놓은 레이아웃이 뜨지 않았다. 몇 번이고 Xcode를 껐다 키고, 컴퓨터까지 껐다 켜봤는데, 딱 그 메인보드에만 렉이 걸려서 아무 동작도 실행되지 않았다.
결국 xcode를 지웠다가 새로 깔기로 결심.
다시 깔아서 실행하니, autoLayout에 오류가 있었는데 계속 컴파일을 시도해서 렉이 걸린 모양이다.
갑자기 Xcode가 멈추더니 TableView를 제외한 그 안의 레이아웃이 통째로 날라갔다.
흠.. 이렇게 렉이 걸릴 수도 있구나.. 생각했다.