[Kotlin/프로그래머스] 24년 2월 1주차 코드카타정리

지혜·2024년 1월 29일

Code_Kata

목록 보기
11/16

✏20240129 월요일

📖문자열 섞기

  • str1과 str2의 길이가 같기 때문에, str1의 인덱스 길이만큼 i가 반복되도록 for문을 작성하고, 그 안에서 빈 문자열 answer에 str1과 str2를 번갈아가면서 붙여주었다.
class Solution {//나의 풀이
    fun solution(str1: String, str2: String): String {
        var answer :String = ""
        for(i in str1.indices){
            answer += str1[i]
            answer += str2[i]
        }
        return answer
    }
}
  • str1.indices.joinToString("") { "${str1[it]}${str2[it]}" } joinToString에 람다식으로 한번에 문자열을 합치는 방법도 있었다.
    이런식으로 사용할수도 있는 줄 처음 알았어서 가져와봤다.
  • 이외에도 str1.zip(str2).joinToString("") { (a, b) -> "$a$b" } zip을 사용해서 str1과 str2를 묶어서 표시하는 방법도 있었는데, 어쨌든 이 풀이도 마찬가지로 joinToString에 대해 람다식으로 합친거라서 몰랐을테지만, zip은 본 적이 있는 함수고 식도 간편해보여서 가지고 왔다.

📖이차원 배열 대각선 순회하기

  • i와j가 각각의 인덱스 값만큼 순회 되도록 이중 반복문을 만들고, 조건에 따라 i+j <= k인 경우에만 그 값이 answer에 담기도록 한 후, sum()을 통해 answer의 합을 반환한다.
class Solution {//나의 풀이
    fun solution(board: Array<IntArray>, k: Int): Int {
        var answer = intArrayOf()
        for(i in board.indices){
            for(j in board[i].indices){
                if(i+j <= k){
                    answer += board[i][j]
                }
            }
        }
        return answer.sum()
    }
}
  • 다른 사람의 풀이를 보니까, board[i][j]의 값이 이미 int형 숫자이기때문에 그 값을 배열에 한 번 더 담을 필요 없이 바로 더하기 연산이 가능했다. 문제 초기값도 var answer : Int = 0 형태였는데, 괜히 intArrayOf()로 바꿔서 sum()을 한 번 더 쓰기나 했다. 다음부터는 타입을 좀 더 고려할 수 있도록 해야겠다.

📖중복된 문자 제거

  • distinct( )를 사용하기 위해 my_string을 toList( )로 한번 바꿔주고, 리스트에서 다시 String으로 타입을 맞춰주기 위해 joinToString("")으로 마무리 한다.
class Solution {//나의 풀이
    fun solution(my_string: String): String 
    =my_string.toList().distinct().joinToString("")
}
  • 사실 맨 처음에 저번에 중복에는 set. 이라는게 너무 머리에 남아서 중복이라는 단어만 보고 set을 활용하는 방법을 생각했다가, 굳이 또 set컬렉션을 선언해서 거기에 다시 myString을 담아서 어쩌고 저쩌고 하면 복잡해질 것 같아서 distinct를 쓰고, 음~ 간단하군. 이라고 생각했는데..
    다른 사람 풀이에 my_string.toSet().joinToString("") 식이 있었다. toSet()!!! toList( ) 처럼 toSet( )도 있을거란걸 왜 생각을 못했을까.. 이제라도 알았으니까 다행이다!ㅎㅎ

✏20240130 화요일

📖날짜 비교하기

  • java.time.LocalDate을 임포트하여 IntArray를 날짜로 바꿔준 후, 날짜가 앞선지 if문을 통해 비교하여 앞서면 1 아니면 0을 반환한다.
import java.time.LocalDate
class Solution {//나의 풀이
    fun solution(date1: IntArray, date2: IntArray): Int {
        val dateA = LocalDate.of(date1[0], date1[1], date1[2])
        val dateB = LocalDate.of(date2[0], date2[1], date2[2])
        
        return if(dateA < dateB) 1 else 0
    }
}
  • 처음에는 compareTo가 먼저 생각났다. 무식하게 IntArray에 바로 적용하고 안되서 해멨다가 if문을 사용해보기로 했는데, if문은 조건을 세세(큰경우, 작은 경우 일일이 0인지1인지 지정해줘야함)하게 걸어주지 않으면 판정이 너무 빡빡해서 점점 코드가 더러워져서 다시 검색하러갔다가 날짜로 아예 변환하면 비교가 쉽다는 걸 알았다. 날짜로 변환하면 compareTo도 사용가능하지만, 그냥 바로 큰지 작은지도 구분 할 수 있다. 날짜 비교하기는 맨날 헷갈렸는데, import가 필요하긴 하지만, 아예 날짜타입으로 변환해서 활용하는 방법이 아주 좋은 것 같다.

✏20240131 수요일

📖글자 지우기

  • my_string에 mapIndexed를 사용해서 인덱스 idx가 indices 안에 있으면 공백문자""를, 아니면 그냥 원래있던 요소c를 반환하도록 하고, joinToString("")으로 타입을 맞춰주었다.
class Solution {//나의 풀이
    fun solution(my_string: String, indices: IntArray): String
    = my_string.mapIndexed{idx,c ->
        if(idx in indices) "" else c
    }.joinToString("")
}
  • 처음에는 removeAt()을 사용해서 해당 인덱스 값을 삭제하는 방법을 사용했는데, removeAt은 mutableLIst에서만 사용이 가능해서, 값을 삭제하고 나면, 인덱스가 자동 정렬되가지고 원하는 값이 아니고 앞당겨진 값들이 삭제되었다..
  • filter도 생각해봤는데, filterNot에는 index랑 같이 활용하는 함수가 없어서 익숙한 mapIndexed를 썼는데, 그냥 filterIndexed에 조건을 부정으로 걸면 되었던 것을 다른 사람 풀이를 보고 알았다... filter는 문자열에서도 사용이 가능해서 map처럼 따로 반환타입을 맞춰줄 필요도 없었다. filterIndexed도 있다는 것을 까먹지 말자!

📖문자열 뒤집기

  • 뒤집히기 전, 뒤집을부분, 뒤집고난 후 3부분으로 substring을 활용하여 나눈 후, 뒤집어야하는 부분에만 reversed()를 사용해서 문자열을 뒤집어주고, 3부분을 합쳐서 반환해준다.
class Solution {//나의 풀이
    fun solution(my_string: String, s: Int, e: Int): String {
        var fornt = my_string.substring(0 until s)
        var reversdStr: String = my_string.substring(s..e).reversed()
        var back = my_string.substring(e+1)
        
        return fornt+reversdStr+back
    }
}
  • 처음에는 중간부분만 바로 바꿔칠 수 있나 생각도 해봤는데, 도저히 그렇게는 안되어서 그냥 따로따로 나눠서 이어붙여줬다.
  • 다른 사람들의 풀이를 보니까 스코프함수를 적극활용하거나, 변수를 굳이 선언하지 않고도 +=, append 등을 활용하여 바로 이어붙이는 풀이도 많았는데, 이게 더 깔끔해보이는 것 같기도하다.

📖문자열 뒤집기 문제의 다른 사람 풀이 : replaceRange를 활용한 풀이

class Solution {//다른 사람 풀이
    fun solution(my_string: String, s: Int, e: Int): String 
    = my_string.replaceRange(s, e + 1, my_string.substring(s, e + 1).reversed())
}
  • replaceRange(startIndex: Int, endIndex: Int, replacement: CharSequence) : CharSequence
    : endIndex는 포함이 안되는 점 유의. replaceRange는 코틀린이 제공하는 문자열 관련 함수로 속도에서 느린 면이 있으니 성능 차이를 고려해서 사용하는 것이 좋다고 한다.
  • 그래도 내가 처음에 생각한 딱 중간 부분만 바로 바꿔주는 함수가 있다는 것을 오늘 새로 알았다.

✏20240202 금요일

📖빈 배열에 추가, 삭제하기

  • flag[i]가 ture일 때는, arr[i]가 arr[i]*2개 만큼 answer에 추가 되어야 하므로, for문을 활용해서 원하는 개수만큼 +=을 사용해서 넣어주었다.
  • flag[i]가 false일 때는, answer의 끝에서 arr[i]개의 원소를 제거해야 하므로 dropLast()를 사용해서 뒤에서부터 arr[i]개 만큼 요소를 제거하고 반환 할 수 있도록 했다. drop함수는 List로 반환해주기 때문에 사용 후 다시 toIntArray()로 타입을 맞춰주었다.
class Solution {//나의 풀이
    fun solution(arr: IntArray, flag: BooleanArray): IntArray {
        var answer: IntArray = intArrayOf()
        for(i in arr.indices){
            if(flag[i]) {
                for(j in 1..arr[i]*2){
                    answer += arr[i]
                } 
            } else {
               answer = answer.dropLast(arr[i]).toIntArray()
            }
        }
        return answer
    }
}
  • 다른 사람들 풀이에서는 flag에 forEachIndexed를 활용한 풀이가 많았는데, 확실히 코드 가독성은 확장함수를 활용하는 것이 좋은 것 같다.
  • arr[i]*2개 만큼 answer에 추가하는 것을 repeat함수를 사용했던데, 유독 repeat이 머리에 안붙는다.. for문이 너무 강력하게 나를 잡고있는 것 같다. 그래도 모르는건 아니라서 늘 repeat이 애매하다. 여튼 repeat을 쓴 풀이가 훨씬 간결해보이긴해서 복잡하지 않은 코드일 때는 repeat을 활용할 수 있도록 유의 해야겠다.

📖빈 배열에 추가, 삭제하기 문제의 다른 사람 풀이 : Stack을 사용한 방법

import java.util.*
class Solution {//다른 사람 풀이
    fun solution(arr: IntArray, flag: BooleanArray): Stack<Int> {
        val stack = Stack<Int>()
        for (i in arr.indices) {
            for (j in 0 until arr[i] * if (flag[i]) 2 else 1) {
                if (flag[i]) stack.push(arr[i]) else stack.pop()
            }
        }
        return stack
    }
}
  • Stack을 사용하기 위해서는 java.util.*을 임포트 해야한다.
  • Stack : 입력 받은 값들을 순차적으로 쌓아서 저장하는 자료구조
  • .push() : 스택에 값을 추가할 때 사용한다.
  • .pop() : 스택의 마지막 값을 (확인하고) 삭제한다.
  • 이외에도 마지막값을 확인만 하는 .peek() 함수와, 크기를 확인하는 size함수, 원소를 찾아주는 .search()함수 등이 있다.

📖1로 만들기

  • num_list의 값들을 for문으로 반복하여, i는 val로 선언되기 때문에 var num에 담아서 1이 될 때 까지 짝수이면 그냥 2로 나누고, 홀수이면 1을 뺀 다음 2로 나눌 수 있도록했다.
  • 모든 원소를 1로 만드는 나누기 연산이 실행될 때마다 answer++을 통해 answer에 +1씩하며 그 값을 반환한다.
class Solution {//나의 풀이
    fun solution(num_list: IntArray): Int {
        var answer: Int = 0
        for(i in num_list){
            var num = i
            while(num != 1){
                if(num % 2 == 0) {
                    num = num/2
                    answer++
                }     
                else {
                    num = (num-1)/2
                    answer++
                }
            }
        }
        return answer
    }
}

📖특정 문자열로 끝나는 가장 긴 부분 문자열 찾기

  • pat이 char타입이 아니고 string타입이기 때문에 pat의 마지막 인덱스 값을 찾아서 그 앞만큼 substring으로 자른 후 pat를 붙여주는 방식으로 문제를 풀었다.
class Solution {//나의 풀이
    fun solution(myString: String, pat: String): String {
        var answer: String = myString.substring(0, myString.lastIndexOf(pat))
        return answer+pat
    }
}
  • 처음에는.. 일단 자른다는 점에 초점이 꽂혀서 split함수를 사용했다. split함수는 기준 요소가 사라지고 List로 반환해주기 때문에 인덱스로 값을 꺼내서 거기에 pat만 붙여주면 되겠다~ 라고 생각했는데 pat 값이 문자열내에서 여러개인 경우에는 pat값 자체가 사라져버리니까 감당이 안되었다..ㅎ 그래서 끝나는에 초점을 맞춰서 lastIndexOf를 활용했더니 아주 쉽게 풀렸다.
profile
파이팅!

0개의 댓글