코딩테스트 언어를 Kotlin으로 바꾼 이유(찐 최종) + 소소한 팁
코딩테스트 언어를 바꾸겠다는 게시글만 벌써 3번째다. 꽤 민망하지만 아마 이번이 진짜 최종 결정일 것이다. (제발)
나름 확고하게 마음을 굳히고 Java로 알고리즘 공부를 하고 있었는데 Kotlin으로 언어를 바꾸게 된 데에는 나름의 이유가 있다.
회사를 다니면서도 나름 꾸준히 알고리즘 문제를 풀어왔고, 현재 내일배움캠프 교육을 듣고있는 와중에도 알고리즘을 꾸준히 풀고 있었다.
현재 듣고있는 교육이 Kotlin을 활용한 안드로이드 교육인만큼, 교육 내에서는 Kotlin으로 알고리즘을 공부하도록 권장하는 것 같았다.
Java로 알고리즘 공부를 계속 해왔기 때문에 교육 내에 상주하는 한 튜터님께 알고리즘 언어 선택에 대한 질문을 하게되었고 Java와 Kotlin 둘 다 사용을 할 줄 안다면, 그리고 Java가 이미 익숙하다면 Java를 사용해도 상관없다는 답변을 받았다. Java을 계속 사용하는 것에 대한 명분으로 내가 생각했던 이유와 동일한 이유를 튜터님도 말씀해주셨다. (현재 Kotlin이 안드로이드 개발 쪽에서 유망한 언어이긴 하지만 아직 제대로 사용된지 오래되지 않았기 때문에, (코딩테스트 한정) Java로 응시가 가능한데 Kotlin으로 응시가 불가한 기업은 있을지언정 Kotlin으로 응시가 가능한데 Java로 응시가 불가능한 기업은 없을것이라는 이유였다.)
그렇게 더이상 언어를 바꾸지않겠다는 마음가짐을 갖고 Java로 알고리즘 공부를 이어가고있었다.
팀원분과 함께 Java로 짠 알고리즘 코드 리뷰를 하고 있던 중, 다른 튜터님께서 "왜 Java를 사용하는지 물어봐도될까요?" 라는 질문을 하셨다.
이어서 하시는 말씀으로는 요즘은 자바를 거의 사용하지않고 코틀린을 많이 쓰는 추세다, 튜터님 회사 같은 경우만 해도 자바로 푸는 사람은 불합격을 주고있다, 자바보다는 코틀린으로 공부하는것을 추천한다, 라는 내용이었다.
인터넷 검색을 해보니, 네이버 계열사만 봐도 2021년 코딩테스트에서 Java는 사용이 불가하고 Kotlin으로만 응시가 가능했다고 한다.
아무렇지 않다고 하면 거짓말이겠지, 아니 솔직히 멘붕이었다.. 이제 좀 Java 문법에 익숙해져서 실력이 늘고 있다고 느꼈는데 다시 또 언어를 바꾸라니..
그럼에도 어쩌겠는가, Python에서 Java로 응시언어를 바꿨던 이유가 안드로이드 직무 코딩테스트에서 사용할 수 없는 언어이기 때문이었는데, 같은 이유라면 Java에서 Kotlin으로 언어를 바꾸는 것에 대해 선택의 여지가 없었다.
어짜피 앞으로 안드로이드 개발을 Kotlin을 사용해서 할거라면 생각보다 나쁘지 않을지도? (라는 위안을 삼아본다..)
그리고 여느때와 같이 Kotlin으로 코딩테스트를 응시하기로 결정한 이상, 코딩테스트를 준비하는데 있어 소소한 팁들에 대해 정리해봤다.
1. 입출력
val num = readLine().toInt() // 정수형 입력
val nums = readLine().split(" ").map { it.toInt() } // 공백 기준으로 자른 List<Int>형 입력
val char = readLine().toCharArray() //CharArray형 입력
println("Print Test")
//BufferedREader, BufferedWriter 사용
val br = BufferedReader(InputStreamReader(System.`in`)) // in은 예약어이기 때문에 ``안에 사용
val brRead = br.readLine()
val bw = BufferedWriter(OutputStreamWriter(Systme.`out`))
bw.write("BufferedWriter Test")
bw.flush() //남아있는 출력 비워주기
bw.close() //스트림 종료
//StringBuilder 사용
val sb = StringBuilder()
sb.append("abc")
sb.insert(2, "ef") // 2 위치 ef 삽입
sb.delete(0, 2) // 0~1 범위 문자열 삭제
sb.deleteChartAt(1) // 1 위치 문자 삭제
sb.setCharAt(1, 'g') // 1 위치 문자 g로 변경
sb.reverse() // 문자열 뒤집기
sb.setLength(1) // 길이 1로 조절 (기존 길이가 1 이상이면 1까지 삭제)
sb.setLength(5) // 길이 5로 조절 (기존 길이가 5 이하면 공백으로 채움)
var arr = arrayOf(1, 2, 3, 4)
arr.forEach { sb.append(it).append(' ') } // 문자열 합치기 (1 2 3 4)
2. 문자열
val strSample = "Hello Kotlin"
strSample.length // > 12
strSample.indices // 0 .. 11
strSample.substring(1, 4) // ell
strSample.slice(1 .. 4) // ello
strSample.find { char -> char == 'l'} // l
strSample.filter { char -> char == 'l'} // lll
strSample.take(3) // lo Kotlin
strSample.replace("Kotlin", "Java") // Hello Java
strSample.isEmpty() // false (문자열 길이가 0이면 true)
strSample.isBlank() // false (문자열 길이가 0이거나 공백이면 true)
strSample.compareTo("abc") // 1 (사전순 str이 앞이면 -1, 같으면 0, 뒤면 1)
strSample.lowercase() // hello kotlin
strSample.uppercase() // HELLO KOTLIN
strSample.reversed() // niltoK olleH
3. 배열
var arr1 = IntArray(size = 3) // [0, 0, 0]
var arr2 = intArrayOf(1, 2, 3) // [1, 2, 3]
println(arr2.joinToString(", ")) //IntArray 출력
arr1.sort() //오름차순 정렬
arr1.sortDescending() //내림차순 정렬
arr1.forEach { value -> println(value) } //배열 모든 값 출력
arr1.forEachIndexed { index, value -> println("${index}, ${value}") } //배열 모든 인덱스, 값 출력
arr1.filter { index -> index == 0 } //조건에 해당하는 값 반환(리스트)
arr1.filterNot { index -> index == 0 } //조건에 해당하지 않는 값 반환(리스트)
arr1.sliceArray(intRange(3, 5)) //인덱스 범위에 따른 배열 반환
arr1.slice(1 .. 3) //인텍스 범위에 따른 리스트 반환
arr1.sum() //배열의 모든 값 합 반환
arr1.sumOf { index -> index * 2 } //조건을 적용한 값의 합 반환
arr1.maxOrNull() //최댓값 반환, 크기가 없는 경우 null 반환
arr1.minOrNull() //최솟값 반환, 크기가 없는 경우 null 반환
println(arr1.contentToString()) //배열의 모든 값 출력
4. 자료구조
//맵 (키는 중복 불가. 사이즈 자동 할당)
val map1 = mapOf(1 to "Kim", 2 to "Lee") //수정 불가능
val map2 = mutableMapOf(1 to "Kim", 2 to "Lee") //수정 가능
map2.keys //맵의 모든 키 반환
map2.values //맵의 모든 값 반환
map2.containsKey(1) //1이라는 Key가 있으면 true, 없으면 false
map2.containsValue("Kim") //Kim이라는 Value가 있으면 true, 없으면 false
map2.getOrDefault(1, "None") //키에 해당하는 값 반환, 값이 없다면 None 반환
map2.remove(1) //1에 해당하는 요소 제거
map2.clear() //맵 초기화
//스택 (가변리스트를 스택처럼 사용이 가능함)
val numbers = mutableListOf(1, 2, 3, 4)
numbers.add(5) //stack.push(5)와 동일
numbers.removeLast() //stack.pop()와 동일
numbers.last() //stack.peek()와 동일
numbers.isEmpty() //비어있는지 확인
//큐 (배열 기반인 ArrayList보다는 LinkedList가 효율적)
val queue = LInkedList<Int>()
queue.offer(3)
queue.peek()
... //등등
//우선순위 큐
val pq = PriorityQueue<Int>() //오름차순 정렬
val pq2 = PriorityQueue(Collections.reverseOrder()) //내림차순 정렬
//데크 (LinkedList보다는 ArrayDeque가 더 효율적)
val deque = ArrayDeque<Int>()
//모두 ..First/Last 존재함
deque.addFirst(1)
deque.removeFirst()
... //등등
참고사이트
https://hanyeop.tistory.com/448