//나누어 떨어지는 숫자 배열
class DivisibleArrayOfNumbers {
fun solution(arr: IntArray, divisor: Int): IntArray =
arr.filter { it % divisor == 0 }
.sorted()
.toMutableList()
.also {
if(it.isEmpty()) it.add(-1)
}.toIntArray()
}
이 문제는 약간의 답을 참고하여 풀었다.
also의 재발견...
also로 객체 자체를 전달받아.. 코드를 한 줄로 스무스하게
만들 수 있는 좋은 메서드이다.
divisor로 나누어지는 요소들을 필터링하고,
오름차순으로 정렬한 다음, 수정할 수 있는 mutableList로 변환해준다.
그리고,
also를 통해 객체를전달받고, 만약 비어 있다면, 리스트에 -1만을 add 해준다.
마지막은 IntArray로 변환하고 반환한다.
제일 작은 수 제거하기
//제일 작은 수 제거하기
class RemoveSmallestNumber {
fun solution(arr: IntArray): IntArray {
return if(arr.size == 1) intArrayOf(-1)
else arr.filter { it != arr.minOrNull() }.toIntArray()
}
}
이 문제는 IntArray에서 제공하는 min()이라는 메서드를 사용하여 풀려고 하는데,
해당 메서드는 Deprecated가 되어, 프로그래머스 에디터에서 계속 resolved가
되는 것이었다.
처음에 Deprecated 된 줄 모르고, 왜 에러가 뜨는지 몰라, 내부를 보니 명시가 되어있었다..
그래서 minOrNull를 대신 쓰라고 친절하게 설명이 되어,
해당 메서드를 사용하여 풀었다.
arr 사이즈가 1이면 -1만을 담은 IntArray를 반환하고,
그게 아니라면, 최솟값만을 제외한 IntArray를 반환하게 하였다.
음양 더하기
//음양 더하기
class AddYinAndYang {
fun solution(absolutes: IntArray, signs: BooleanArray): Int =
absolutes.also {
signs.mapIndexed { i, b ->
if(!b) it[i] *= -1
}
}.sum()
}
이번에도 깔끔하게 한 줄로 나타내게 하기 위해
also로 쓴 방법이다.
그런데, 이 방법을 사용하고 나서 더 효율 좋고 간단하고 유용한 메서드를 사용한 답안을 보았다.
아래 코드이다.
//음양 더하기
class AddYinAndYang {
fun solution(absolutes: IntArray, signs: BooleanArray): Int =
absolutes.foldIndexed(0) { idx, acc, num ->
acc + if(signs[idx]) num else -num }
}
바로 foldIndexed() 메서드이다..
나는 이 메서드가 생소하여 공부해보았다.
fold라는 메서드가 있는데, 이 메서드는 계산 결과를 저장하는 누산기를 제공한다.
누산기(accumulator)를 제공한다는 말이 어려울 수 있다.
fold 메서드의 사용법을 간단히 알아보자.
val intArr = intArrayOf(1, 2, 3)
val result = intArr.foldIndexed(0) {
idx, acc, num -> num
}
foldIndexed는 처음에 accumulator의 초깃값을 정해야하한다. (코드에서는 0으로 지정했다.)
그리고 다음과 같이 인덱스(idx), 누산기(acc 초깃값 0), 배열의 요소(num)를 전달받게 된다.
여기서 idx와 num을 전달받는 것까지는 이해할 수 있겠지만,
저 acc(누산기)는 어떻게 활용할까?
쉽게 말하자면 누산기와 같이 연산하게 되면, 값이 저장되게 된다.
아래 코드를 보면서, 쉽게 이해가 갈 것이다.
//case 1: acc에 값을 연산하지 않았기 때문에(누산하지 않았기 때문에) 저장되지 않고,
//마지막 요소 3이 출력된다.
val intArr = intArrayOf(1, 2, 3)
val result = intArr.foldIndexed(0) {
idx, acc, num -> num
}
print(result) //3
//case 2: 이 역시 acc에 값을 누산하지 않았기 때문에, 마지막 인덱스 값인 2가 출력된다.
val intArr = intArrayOf(1, 2, 3)
val result = intArr.foldIndexed(0) {
idx, acc, num -> idx
}
print(result) //2
//case 3: acc에 값을 누산하지 않았기 때문에 초깃값으로 설정한 0이 출력된다.
val intArr = intArrayOf(1, 2, 3)
val result = intArr.foldIndexed(0) {
idx, acc, num -> acc
}
print(result) //0
//case 4: 왼쪽 요소 부터 차례대로 1, 2, 3씩 acc(0)에 값을 더하며 누산하였기 때문에,
//6이 출력된다.
val intArr = intArrayOf(1, 2, 3)
val result = intArr.foldIndexed(0) {
idx, acc, num -> acc + num
}
print(result) //6
//case 5: 요소들의 인덱스 값이 0, 1, 2 값이 acc(0)에 값을 더하며, 누산하였기 때문에,
//3이 출력된다.
val intArr = intArrayOf(1, 2, 3)
val result = intArr.foldIndexed(0) {
idx, acc, num -> acc + idx
}
print(result) //3
역시 말보다는 코드로 설명하는 게 이해가 가기 쉬울 것이다.
한마디로 전달받은 누산기(acc)에 값을 차례대로 계산하여 저장하는 느낌이라고 생각하면
쉬울 것이다.
차례로 계산할 때 유용한 메서드가 될 것 같다.
그럼 다시 한번 코드를 보게 되면,
//음양 더하기
class AddYinAndYang {
fun solution(absolutes: IntArray, signs: BooleanArray): Int =
absolutes.foldIndexed(0) { idx, acc, num ->
acc + if(signs[idx]) num else -num }
}