오늘은 드디어 프로젝트가 마무리되는 발표일이었습니다.
아침부터 그렇게 피곤하지도 않았지만, 발표라는 생각에 긴장됐습니다.
그렇게 일단은 코드 카타부터 풀고 있었는데...
정답은 맞는 것 같은데, 시간이 너무 오래 걸려서 시간 초과로 끊기는 일이 일어나버렸습니다.
그래서 이것저것 줄여보고 한 끝에 4시간만에 해결했습니다...
상세한 내용은 코드 카타 부분에서 적겠습니다.
그 후, 17시 30분부터 18시까지 짧게 코틀린 공부를 하고
식사 후, 마인드셋 세션을 듣고 난 뒤, 코틀린 공부를 마쳤습니다.
09:30 ~ 11:30, 15:00 ~ 17:00
이번 코드 카타는 조금 어려웠던 거 같습니다.
어떻게 풀어야 할지는 알겠는데 코드를 짜는 과정이 문제였습니다.
제가 처음 생각한 해결 방식은, (1, 2, 3, 1) 세트를 빼버리는 것이었습니다.
하지만, 제가 아는 선에서는 마땅히 쓸 만한 게 떠오르지 않았고 이 방법은 넘겼습니다.
두 번째 해결 방식은 처음부터 세는 것이었습니다.
처음부터 세서 1, 2, 3, 1 순서대로 있으면 카운트하고, 그 부분을 잘라내는 방식이었습니다.
하지만, IntArray를 자르는 방법 또한 몰랐기 때문에
제가 선택한 방식은 기존 값들을 없애고, 뒤의 값들을 가져와 덮는 것이었습니다.
그렇게 해서 만든 코드를 돌려보니...
세상에... 아무래도 for문 천지이고, 값을 구할 때 앞으로 계속 돌아가서 시간이 초과된 것 같습니다.
그리고, 저는 필요없는 for문 줄여서 해결하겠다 생각했지만,
그렇게 3시간동안 정답을 찾지 못했습니다.
발표로 인한 긴장감, 왜 안 풀리는지 모르겠는 답답함.
여러 감정들에 짓눌려 힘들어서 잠시 쉬면서 생각했습니다.
이건 평생 내가 못 푸는 문제인가?
하지만 이걸 인터넷에 검색해서 풀거나, AI의 도움을 요청하기는 싫었습니다.
남의 도움을 받아 알고리즘 문제를 해결하는 건 정말 최후의 최후까지 가서 선택하고 싶었거든요.
그래서 저는 코드를 싹 다 지웠습니다.
그리고 제가 생각할 수 있는 대로 최대한 압축해서 다시 작성했습니다.
아래는 해당 코드입니다.
class Solution {
fun solution(ingredient: IntArray): Int {
var answer: Int = 0
val firstOne = ingredient.indexOf(1)
var i = firstOne
if(ingredient.size < 4) return answer
while(i <= ingredient.size - 4) {
var count = 0
for(j in 0..3) {
if(ingredient[i+j] == ((j % 3) + 1)) count++
else if(ingredient[i+j] == 0) return answer
else break
}
if(count == 4) {
answer++
for(j in i..ingredient.size - 4) {
if(j < ingredient.size - 4) {
ingredient[j] = ingredient[j+4]
ingredient[j+4] = 0
}
else ingredient[j] = 0
}
if(i < 2) i = -1
else i -= 3
}
i++
}
return answer
}
}
정답이라는 메시지가 떴고, 그 후에 다른 사람들이 푼 풀이를 보았습니다.
역시나 제일 단순한 게 정답이었습니다. 풀이 방식 자체는 간단하지만, 문법을 알고 있어야 풀 수 있었습니다.
가장 많이 선택한 게 앞에서부터 반복하면서, StringBuilder로 잘라내고 다시 반복하는 식이었습니다.
오늘 코드 카타를 하면서 가장 크게 느낀 점은
역시 문법 공부가 중요하다는 것과, 이걸 실제로 자주 사용해보고 익혀야겠다는 생각이었습니다.
그리고, 결국 제 생각이 맞으면, 안 풀리는 문제가 없다는 것도 느꼈습니다. 더럽긴 하지만 정답이니깐요.
어쨌든, 그래서 오늘은 Kotlin 문법을 공부해보겠습니다.
17:00~18:00, 20:00~21:00
어제는 다른 언어라면 기본적으로 있는 함수, if, 반복문, 문자열과
코틀린의 3개의 컬렉션들(List, Set, Map)을 공부했습니다.
그리고 약간의 확장함수들도 공부했습니다.
오늘은 아토믹 코틀린의 3부에 해당하는 사용성이라는 파트를 공부하려고 합니다.
해당 파트에서는 코드를 짜면서 유용한 문법들을 소개하고 있습니다.
특히나 제가 조금 어려워 했던 부분들이 있어, 그 부분들을 제대로 짚고 넘어가도록 하겠습니다.
함수는 기본적으로
fun 함수명() {}
으로 씁니다. 근데 몇몇 함수들을 보면 .함수명 이런 식으로 붙여서 쓰는 경우가 있습니다.
그 경우가 확장 함수입니다. 확장 함수는
fun 타입.함수명() {}
으로 쓸 수 있습니다. 저기서 타입은 리턴 값이 아니라 확장함수를 쓸 수 있는 타입입니다.
이 확장 함수를 사용하면 중위 함수도 만들 수 있습니다.
infix fun 타입.함수명(매개변수) {}
중위 함수라는 건 함수명이 가운데 있다는 뜻입니다.
이 두 종류의 함수는 특이한 형태로 호출합니다.
기본 함수: 함수명(인자)
확장 함수: 인자.함수명()
중위 함수: 인자1 함수명 인자2
중위 함수같은 경우는 위처럼 쓰이기 때문에 하나의 매개변수가 필요합니다.
코틀린의 인자는 특이합니다. 매개변수의 이름을 사용해서 순서를 무시할 수 있습니다.
fun 함수명(a: Int, b: Int) {}
함수명(b=1, a=2)
위 경우, 제대로 해당 매개변수에 인자값이 들어감
그리고, 디폴트 값을 넣어줄 수도 있습니다.
fun 함수명(a:Int = 2) {}
이 두 가지의 인자 사용 방식은 특히나 Jetpack Compose의 Composable 함수들을 다룰 때 많이 봤었습니다.
덕분에 익숙한 문법이었네요.
코틀린에서는 switch-case문 대신 when식을 사용합니다.
저는 개인적으로 when 식이 되게 잘 만들어진 것 같습니다.
when(변수) {
값1 -> 결과1
값2 -> 결과2
else -> 디폴트 결과
}
위는 변수가 값1일 때, 결과1을 보여주고, 값2일 때는 결과2를, 나머지 경우에는 디폴트 결과를 보여줍니다.
else -> 의 경우, 일반적으로는 무조건 설정해줘야 합니다.
하지만, 모든 값에 대한 결과가 있다면 설정하지 않아도 됩니다.
코틀린에서 Class 앞에 붙일 수 있는 키워드가 존재합니다.
기본적으로는 닫힌 상태이기 때문에, 상속을 하려면 open class를 사용해야 합니다.
그 외에도 enum class와 data class라는 것도 존재합니다.
먼저 enum class는 enum과 비슷합니다. 클래스를 나열해서 사용할 수 있어요.
enum class 클래스명() { 나열클래스1, 2, 3,... }
enum class ABC() { ABCdd, ABCAA, DWDW }
그리고 이렇게 나열한 enum들은 클래스.이넘명으로 불러올 수 있습니다.
또한 안에 매개변수가 있다면, 다른 이넘들은 그 변수에 대한 인자값을 가져야 합니다.
enum class ABC(i: Int) { ABCdd(1), ABCAA(3), DWDW(0) }
보통 enum은 나열이라는 개념이 강하기에, 해당 부분을 신경쓰면서 작성하면 될 것 같습니다.
data class는 값들을 저장하는 클래스입니다. 그래서 클래스를 마치 데이터처럼 쓸 수 있습니다.
data class 클래스명(
val a: Int
val b: String
) { }
위처럼 a, b같은 변수들을 데이터로 쓸 수 있습니다.
데이터로 쓴다는 뜻은 즉, 클래스 자체에 toString(), copy() 등의 확장함수를 사용할 수 있다는 뜻입니다.
일반적으로 class에 toString() 하면 이상한 값이 나오겠지만, data class는 클래스명, 어떤 데이터들이 있는지를 보여줍니다.
대신, 생성자 부분에 데이터들을 선언해줘야 합니다.
이번주는 이렇게 끝이 났습니다.
일주일동안 같이 해준 팀원들께 고맙다고 말씀드리고 싶고...
꼭 다음에도 같이 작업할 수 있었으면 좋겠습니다!
다음주는 제가 예비군을 가서 못 쓸 것 같습니다.
끝
참고 자료