2차원 배열 도전기

김태영·2024년 5월 13일
0

TIL

목록 보기
8/70
post-thumbnail

2차원 배열 다루기

주어지는 두 정수 배열의 행과 열이 같은 원소들을 더한 배열을 구하면 되는 문제였다. 2중 for 문을 사용하는 방법도 있겠지만, for 문 기피증이 있는 나는 (이유는 없다) forEachmap을 사용해 풀고싶었다. 그래서 가독성은 좀 안좋지만 2중으로 mapIndexed를 사용해 풀었는데, 세상에나 2차원 IntArray로 쉽게 바꿀 수 있는 게 아니었다.

arr1.mapIndexed { i, a -> a.mapIndexed { j, aa -> aa + arr2[i][j] } }
// List<Array<Int>> 타입

주석에서처럼, 내부 원소가 Int형인 Array가 들어가 있는 리스트로 변환이 되는데 이를 Array<IntArray>로 변환해야 했다. 찾아보니 먼저 내부의 Array<Int> 타입을 IntArray로 바꿔주고, 다시 toTypedArray를 통해 변환하는 방법이 있었다.

toTypedArray()
: 원래 컬렉션의 요소 타입과 동일한 요소 타입을 가진 배열을 생성해준다.

arr1.mapIndexed { i, a -> a.mapIndexed { j, aa -> aa + arr2[i][j] }.toIntArray() }.toTypedArray()

꼭 이런 형태여야 할까? 싶어서 toIntArray만 두 번 써보기도 하고, toTypedArray만 써보기도 하고 여러가지 해봤지만 위와 같은 형태만 성공을 했다. 문제에서 Array<IntArray> 타입을 원했기 때문에 당연한 사실이긴 하다.. 그래도 궁금한걸

풀고나서 보니, 배열을 생성할 때 초기화 단계에서 끝내버린 사람도 있었다. 아직 배열 초기화까지 써보지는 않았는데, 알아두면 도움이 될 것 같다.

Array(arr1.size) { row -> 
										IntArray(arr1[0].size) { col ->
					                arr1[row][col] + arr2[row][col] } }

2차원 배열을 초기화 하는 건 아직 너무 어려워 보이지만..! 익숙해질 수 있겠지..!

!! 연산자

드디어 처음으로..! 사용자의 입력을 받는 코드를 작성해봤다. 사실 작성은 아니고 문제 풀이란에 미리 적혀져 있었다. 그 코드 중에서 !! 가 사용되었는데, 대충 느낌상 옵셔널을 푸는 것 같지만 조금 더 정리된 문장으로 기억해두고 싶어서 알아보았다.

val (n, m) = readLine()!!.split(' ').map(String::toInt)

readLine() 함수가 항상 null이 아닌 값을 반환한다고 가정하고, 그렇지 않을 경우에는 예외를 발생시키는 방법이라고 한다. 사용자의 입력이 없을 수 있으니 readLine() 함수는 입력 값을 Nullable로 다루는 것 같다. 역시나 코틀린 문서를 확인해보면, String? 타입인 걸 확인할 수 있다!

fun readLine(): String?

유클리드호제법

주어지는 두 수의 최대 공약수와 최소 공배수를 구하는 문제를 풀어보았다. 사실 이전에 파이썬으로 한 번 푼 적이 있었던 문제였는데, 문제는 기억이 안난다는 거다. 다행히 주석으로 유클리드호제법을 적어놔서 휴지통에 있던 기억을 겨우겨우 복원해 풀어보았다.

def solution(n, m):
    # 유클리드호제법 - 최대공약수
    gcd = lambda a, b: gcd(b, a%b) if a%b else b
    return [gcd(n, m), n*m/gcd(n, m)]

코드를 확인해보니 대충 유클리드호제법이 무엇인지 알 것 같다.

두 수 a와 b의 최대 공약수는 b와 a를 b로 나눈 나머지의 최대 공약수와 같고, 이를 나머지가 0이 될 때까지 반복하면 a와 b의 최대 공약수를 구할 수 있다.

참고로 최소 공배수는 두 수의 곱을 최대공약수로 나누면 된다. 나는 까먹어서 또 찾아보았다. ㅎ..

아무튼 최대 공약수는 코틀린의 재귀 함수를 사용해 풀어보았다. 알게 된 지 얼마 안됐는데 생각보다 금방 사용하게 돼서 전에 미리 알아보길 잘 한 것 같다.

tailrec fun gcd(x: Int, y: Int): Int = if (x % y == 0) y else gcd(y, x%y)

그런데 세상에나, 어차피 y에 들어오는 건 나머지기 때문에 조건을 아예 if (y == 0) 으로 해도 되는 거였다! 이렇게 또 알아간다..

10진수를 3진수로 변환

10진수를 3진수로 변환한 후, 거꾸로 뒤집은 수의 10진수를 구하는 문제였다. 나는 코틀린에 3진수로 변환하는 함수가 따로 없는 줄 알고 너무나 정직하게 풀어버렸다.

fun solution(n: Int): Int {
  var s = ""
  var div = n

	// 3진수 변환 (거꾸로)
  while (div != 0) {
    s += (div%3).toString()
    div /= 3
  }

  return s.toInt(3)
}

사실 3진수를 10진수로 변환하는 함수도 없을 것 같아서 반복문을 쓰려다가 혹시…? 하는 마음에 찾아봤더니 toInt(변환할진법) 를 사용하면 가능하대서 이걸 이용해 풀었는데…

toString()도.. 같은 방식으로.. 사용이.. 가능하다..

n.toString(3).reversed().toInt(3)

오늘도 어김없이 뒤통수를 맞은 나다. 그래. 모르면 당해야지. 다음엔 안당할 자신 있다.

profile
화이팅

0개의 댓글