Long 형과 친목도모

김태영·2024년 5월 8일
0

TIL

목록 보기
5/70
post-thumbnail

두 변수의 값 바꾸기

파이썬에서는 간단히 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

친해지자 Long..

두 정수 사이의 수를 모두 더한 값을 구하는 문제였다. 물론, 문제에서 주어지는 수의 범위가 나오긴 했지만..! 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 와 Long 의 범위

  • 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()

더 친해지자 Long..

같은 문제로 실패를 맞이한 풀이가 있다. 콜라츠 추측 문제였는데, 처음에는 단순히 문제 그대로 코드에 담아 풀었었다.

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 키워드를 붙여주면 되는데, 이 때 함수의 마지막 작업이 자기 자신을 호출하는 형태여야 한다고 한다. 사실 재귀 함수를 알고 있었더라도 구현하는 데 좀 어려웠을 것 같다. 나중에는 나도 예쁘게 재귀 함수를 작성하는 날이 오겠지?

profile
화이팅

0개의 댓글