알고리즘 5+1

Kotlin diary (1) - 자주 사용했던 것들

일반정보 2021. 5. 30. 09:10

들어가는 글

이번시간에는 잠시 쉬어가는 글로, 제가 알고리즘 문제를 풀면서 조금씩 정리했었던 것들을 10개정도 모아보았습니다. 이렇게 이따금씩 올려보는 것도 좋을 것 같아 이렇게 올리게 되었습니다. 

예제 코드는 https://play.kotlinlang.org/ 에서 확인해 보실 수 있습니다. 

 

 

1. 문자열 제어 (StringBuilder 사용) 

제가 아주 예전에 당황했던 것은, 문자열은 처음 선언됨과 동시, 바꿀 수 없다는 것이였습니다. 코틀린에서는 이렇게 StringBuilder를 지원합니다. 이렇게 하면 문자열을 순회함과 동시에, 해당 인덱스의 요소를 변경하거나 할 수 있습니다. 

fun main() {
    
   var str = StringBuilder() 
   
   str.append("hello")
   println(str)
   
   for(i in 0 .. str.length - 1){
   
           str[i] = str[i] + 1
   }
   
   println(str)
}

 

2. 문자열 분리, 합체 (String -> list -> String) [chunked(), joinToString()]

1번때 제가 당황했었다고 했는데 그때 어찌할 바를 몰라서 이렇게 했었던 경험이 있었습니다. chunked()는 String의 글자 수마다 나누어 주어 List로 만들어 주는 것인데, chunked(1)를 하게된다면 글자마다 나누어 리스트로 만들어 주는 것이죠. 물론 이렇게 한다고 해서 List도 요소 변경은 안 되기 때문에 CharArray 나 MutableList로 바꾸거나 해야 할 것 입니다. 

참고로 chunked()는 몰라도 joinToString()는 꽤 많이 사용했었던 것 같습니다. 

fun main() {
    
   
    var S : String = "Hello"
    
    println(S.chunked(1))
    println(S.chunked(1).joinToString(""))
}

 

3. 간단한 정렬 sorting + pair

코틀린이 함수형 프로그래밍을 지원한다는 것을 감사하는 바입니다. 아래 코드는 pair에서 각각 first , second 그리고 first와 second를 각 가눈 값을 기준으로 내림차순으로 정렬하는 코드 입니다. 

다른 언어는 어떠한 방법이 있는지 나중에 한번 알아보아야 겠지만, 코틀린의 경우는 이렇게 간략하게 쓸 수 있다는 것이 큰 장점인 것 같습니다. 

fun main() {
    
  val WnV = mutableListOf(3 to 5, 4 to 5, 2 to 3 , 3 to 4) 
  
  	WnV.sortBy{it.first}
    println("first 기준 오름차순 : $WnV \n")
     
     
	WnV.sortBy{it.second}
    println("second 기준 오름차순 : $WnV \n")
     
     
    WnV.sortByDescending{ it -> it.second.toFloat() / it.first.toFloat() }
    println("second / first 기준 내림차순 : $WnV \n")

}

 

4. N개의 요소를 겹치지 않고 선택하기 

리터럴에서 N개의 요소를 겹치지 않고 선택하는 경우입니다. 선택해야 할 요소가 정해져 있을 때 유용합니다. 물론 스트림 함수를 사용해서 아래 코드보다 더 간략하게 하는 코드도 보았습니다.  그래도 아래 코드는 코드를 보면 한번에 개념을 알 수 있을 정도로 쉬운코드라. 무지성으로 코드를 작성해야 할 때 유용? 합니다. 

fun main() {
    
    val nums : MutableList<Int> = mutableListOf(1,2,3,4,5,6)
    
    
    for(i in 0 until nums.size - 2){
            for(j in i + 1 until nums.size - 1){
                for(k in j + 1 until nums.size){
                    
                    print(nums[i]) 
                    print(nums[j]) 
                    println(nums[k]) 
                    
                }
            }
        }
    
    
}

 

5. 소수 판별하기

소수를 판별하는 방법입니다. 아래 코드를 간략하게 요약하면 우선 2를 제외한 나머지 짝수는 소수가 아닙니다. 그리고 3이상의 소수들로 나누었을 때, 그 소수의 약수이면 나누어 떨어질 것이므로 나누어 떨어지면 소수가 아닙니다. 

이도 간결한 코드를 알고 있습니다. 하지만 이 코드가 가장 직설적이라 이해하는데는 편하죠

fun main() {
	println(isPrimeNum(5)) 
}



 fun isPrimeNum( num : Int ) : Boolean {
        
        if(num == 2) return true
        if(num%2 == 0) return false
        else{
            for(i in 3 .. num - 1 step 2){  
                if(num%i == 0) return false        
                 }   

            return true
            }
    }




 

6. 문자열에 표현식 사용하기

의외로 잘 사용해서 여기에 넣었같습니다. 리눅스의 쉘 스크립트가 생각나는 사용법입니다. 

fun main() {
   var a = 1
   var str1 = "a = $a"
   var str2 = "a = ${a + 5}"
    
   println("$str1   $str2")
   
}

 

7. 함수를 만드는 3가지 방법

코틀린에서 대표적으로 함수를 만드는 방법입니다. 모두 같은 함수이며, 또한 코틀린은 형식을 추론할 수도 있기 때문에 sum3처럼도 사용할 수 있습니다.

fun main() {
    println(sum1(1,2))
    println(sum2(1,2))
    println(sum3(1,2))
}

fun sum1(a : Int , b : Int) : Int {
  return a + b
}

fun sum2(a : Int , b : Int) : Int = a + b

fun sum3(a : Int , b : Int) = a + b

 

8. 동적으로 배열 생성하는 법  + 배열 자르기

이 부분도 제가 코틀린를 처음 시작했었을 때 당황했었던 부분입니다. 처음에는 arrayOf()를 주로 사용하다보니 배열의 크기를 설정할 수 없는 줄 알았던 기억이 있었습니다. 아래코드에서는 10크기의 IntArray를 생성하면서 0으로 초기화 시키고 있습니다. 

배열을 인덱스범위로 자를 때도 가끔 있었는데 그럴때는 sliceArray()를 사용합니다. (toList()는 별거 없습니다. 배열을 출력할때 내용을 간단히 확인하는 것 뿐이라면 deeptoString() 보다 리스트로 변환하는게 편하기 때문입니다. )

fun main() {
    
    val arraySize = 10
   	val arr = IntArray(arraySize ,{0})
    
    println(arr.sliceArray(1 .. 5).toList())
}

 

9. 순회에서 요소를 삭제할 때 주의점

또다시 제가 당황했던 부분 입니다. 순회 도중에 배열, 리터럴 등에 drop이나 remove를 해버리면 에러가 뜨게 됩니다. 다른 방법을 사용하거나. 아래 처럼 요소의 remove이후 바로 break를 해 주어서 순회를 종료 시켜야 합니다.

fun main() {
    
    var ls = mutableListOf(1,2,3,4,5,6,7)
    var removeNum = 5
	
    for(i in 0 .. ls.size -1){
        
        if(ls[i] == removeNum){ 
            ls.removeAt(i)
            break  // 이 줄을 제거하면 에러가 나게 됩니다.
        }  
    }
    
    println(ls)
    
}

 

10. Set의 활용 (중복의 제거)

set은 중복된 요소를 줄일수 있고, 또 아래 코드처럼 서로 다른 두 set에서 같은 요소를 제거하기에 용이합니다. 아래 코드는 ls1에 있는 0의 요소를 모두 제거하는 방법입니다. 이 방법도 자주 사용했었던 것 같네요

fun main() {
    
    var ls1 = listOf(1,2,0,0,0,3,4,5,0,0,6,7)
    var ls2 = listOf(0)
	
    println(ls1.toSet() - ls2.toSet())
    
}