파이썬에서는 간단히 a, b = b, a
를 이용해 바꿀 수 있었는데, 코틀린은 임시 변수를 이용하는 방법 외에 다른 방법이 없을까 궁금증이 생겼다.
코틀린에는 also
라는 함수가 있다고 한다. also
는 블록 내부의 연산을 수행한 뒤, 원본 객체를 그대로 내보낸다. 즉, 다음과 같은 코드는 a 변수에 b 변수의 값이, b 변수에는 a 변수의 값이 들어가게 되는 것이다!
a = b.also { b = a }
문제를 풀다가 새로 알게된 것이 있어서 꼭 메모해놓고 싶었다. 까먹으면 안된다.
크기를 선언하지 않은 배열에는 원소 추가가 불가한 줄 알았는데, 코틀린 IntArray 클래스의 +
연산자를 재정의한 함수가 있다고 한다! 따라서 다음과 같은 코드가 가능하다.
var test = intArrayOf()
test += 1
test = test.plus(3) // .plus() 사용에는 주의하자
test.map { println(it) } // 1 3
두 정수 사이의 수를 모두 더한 값을 구하는 문제였다. 물론, 문제에서 주어지는 수의 범위가 나오긴 했지만..! Int 형이 정확히 어느 정도의 범위까지 처리할 수 있는지 알고있지 않아서 반환만 Long 형으로 풀이했었다.
class Solution {
fun solution(a: Int, b: Int): Long {
return if (a == b) a.toLong() else if (a > b) (b..a).sum().toLong() else (a..b).sum().toLong()
}
}
그러나 코드를 이리저리 바꿔봐도 일부의 테스트만 계속 실패하는 것이다. 찾아본 결과, 합 연산 중에 Int 범위를 넘어가서 생기는 문제라고 한다..
Int
: -2^32 .. 2^31 -1 (-21억 4748만 3648 .. 21억 4748만 3647)Long
: -2^63 .. 2^63 -1 (-992경 .. 992경)그래서 범위 자체를 Long 형으로 만드는 방식으로 해결해보았다.
class Solution {
fun solution(a: Int, b: Int): Long {
return if (a == b) a.toLong() else if (a > b) (b..a.toLong()).sum() else (a..b.toLong()).sum()
}
}
다음은 다른 사람의 풀이 중 가장 기억에 남는 코드이다. 굳이 두 수가 같을 때를 생각하지 않아도 됐겠다라는 것을 알게되었다.
val start : Long = (if(a>b) b else a).toLong()
val end : Long = (if(a>b) a else b).toLong()
return (start..end).sum()
같은 문제로 실패를 맞이한 풀이가 있다. 콜라츠 추측 문제였는데, 처음에는 단순히 문제 그대로 코드에 담아 풀었었다.
class Solution {
fun solution(num: Int): Int {
var number = num
if (num == 1) return 0
for (i in 1..500) {
number = if (number % 2 == 0) number / 2 else number*3 + 1
if (number == 1) return i
}
return -1
}
}
이전 문제는 테스트라도 다 통과했지 요번 문제는 글쎄 테스트도 통과하지 못하는거다! 한 번 당했지 두 번은 안 당한다는 마인드로 Long 형을 이용해서 다시 풀어보았다.
class Solution {
fun solution(num: Int): Int {
var number = num.toLong()
if (num == 1) return 0
for (i in 1..500) {
number = if (number % 2 == 0L) number / 2 else number*3 + 1
if (number == 1L) return i
}
return -1
}
}
결과는 성공! 꼭꼭 정확하게 처리할 수 있는 수의 범위를 알아두도록 하자.
다른 사람의 풀이 중 tailrec
이라는 꼬리 재귀 함수를 사용한 코드가 있었다.
class Solution {
fun solution(num: Int): Int = collatzAlgorithm(num.toLong(),0)
tailrec fun collatzAlgorithm(n:Long, c:Int):Int =
when{
c > 500 -> -1
n == 1L -> c
else -> collatzAlgorithm(if( n%2 == 0L ) n/2 else (n*3)+1, c+1)
}
}
함수 앞에 tailrec
키워드를 붙여주면 되는데, 이 때 함수의 마지막 작업이 자기 자신을 호출하는 형태여야 한다고 한다. 사실 재귀 함수를 알고 있었더라도 구현하는 데 좀 어려웠을 것 같다. 나중에는 나도 예쁘게 재귀 함수를 작성하는 날이 오겠지?