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

지혜·2024년 1월 8일

Code_Kata

목록 보기
8/16

✏20240108 월요일

📖두 수의 연산값 비교하기

  • if문을 사용하여 a,b수를 합쳐서 Int타입으로 변환한 수와 2*a*b를 비교하여 큰 숫자가 나오도록 반환값을 주었다.
class Solution {//나의 풀이
    fun solution(a: Int, b: Int): Int 
    = if("$a$b".toInt() >= 2*a*b) "$a$b".toInt() else 2*a*b
}
  • 쉬운 문제지만, 풀이가 좀 지저분한 것 같아서 마음에 안들었는데, 마침 다른 사람들의 풀이에 처음보는 함수도 있고, 깔끔한 풀이도 있어서 공부하고자 가져왔다.

📖두 수의 연산값 비교하기 문제의 다른 사람 풀이

  1. class Solution {//다른 사람 풀이
        fun solution(a: Int, b: Int): Int {
            var answer: Int = 0
            val aa = (a.toString() + b.toString()).toInt()
            answer = aa.coerceAtLeast(a*b*2)
            return answer
        }
    }
  • coerceAtLeast 함수를 사용한 방법
    • coerceAtLeast : 호출된 객체가 특정 객체보다 큰 지 아닌지 확인하여 호출된 객체가 더 클 경우 객체를 반환, 아니면 최소 객체를 반환.
    • coerceAtMost : 호출된 객체가 특정 객체보다 작은지 아닌지를 확인하여 호출된 객체가 더 작은 경우 객체를 반환, 아니면 최대 객체를 반환
  • 진짜 처음보는 함수라서 가져왔다. 이 문제에 진짜 적합한 함수 같다.
  1. class Solution {//다른 사람 풀이
        fun solution(a: Int, b: Int): Int = maxOf("$a$b".toInt(), 2 * a * b)
    }
  • maxOf를 통해 kotiln.math.* 를 임포트할 필요없이 바로 두 수의 비교가 가능하다.
  • max를 사용하려고 하면 보통 임포트해야해서, 뭔가 잘 손이 안갔는데,, maxOf를 보고 살짝. 허망..한 기분? 이런 편리한게 있었다니. maxOf는 뒤에 람다식을 사용해서 여러값중에 가장 큰 값을 반환해주는 함수이기 때문에, 숫자 2개를 1:1 비교하는 것 외에도 활용도가 높은 함수이다.!

📖첫 번째로 나오는 음수

  • 음수가 없다면 -1을 반환하기 때문에, -1을 초기화 값으로 할당하고, for문을 활용하여 음수를 찾은 뒤, 음수가 있다면 해당값의 인덱스를 반환하고 반복문을 빠져나오도록 작성 했다.
class Solution {//나의 풀이
    fun solution(num_list: IntArray): Int {
        var answer: Int = -1
        
        for(i in num_list){
            if(i < 0) {
                answer = num_list.indexOf(i) 
                break
            }
        }
        return answer
    }
}
  • indexOf가 해당 값이 없으면 -1을 반환하기 때문에, 활용해서 풀고 싶었는데.. 검색까지 해봤지만. 음수 조건을 .. 어떻게 붙여줄까 고민하다가 그냥 이렇게 작성했다. 검색했을 때.. indexOf랑 lastIndexOf 까지는 보고, 왜 indexOfFirst는 못봤는지.. 다른 사람풀이에서 보고 역시 또 아쉬움이 컸다.

📖첫 번째로 나오는 음수 문제의 다른 사람 풀이 : indexOfFirst를 사용한 풀이

class Solution {//다른 사람 풀이
    fun solution(numList: IntArray) = numList.indexOfFirst { it < 0 }
}
  • indexOfFirst : 람다식에 일치하는 첫 요소의 인덱스를 반환하고, 일치 하는 것이 없으면 -1을 반환한다.
  • indexOfLast : 람다식에 일치하는 마지막 요소의 인덱스를 반환하고, 일치하는 것이 없으면 -1을 반환한다.
  • indexOf(element:E) : 인자로 받은 요소가 첫 번째로 나타나는 인덱스를 반환하며, 없으면 -1을 반환한다. 람다식 사용 불가능
  • lastIndexOf(element:E) : 인자로 받은 요소가 마지막으로 나타나는 인덱스를 반환하고, 없으면 -1을 반환한다. 람다식 사용 불가능

📖공백으로 구분하기 1

  • split(" ") 을 사용하여 공백을 기준으로 잘라내고, List<String>타입으로 추론 할당된 값을 다시 toTypedArray( )를 사용해 배열로 바꿔서 타입을 맞춘 후 반환시켜주었다.
class Solution {//나의 풀이
    fun solution(my_string: String): Array<String>
    = my_string.split(" ").toTypedArray()
}
  • split이 바로 list형태로 반환하는 지 이 문제를 풀면서 알았다. 그냥 자르기만 하는 줄 알았는데.. 생각해보면 자르고 전체 값을 가지고 있어야하니까 어딘가에 담겨있어야 하는 모습이 적절한 것 같다.
  • split 함수는 리스트형태로 반환해주기 때문에, 각 인덱스를 활용하여 첫번째로 잘린 값, 두번째로 잘린 값 .. 등을 따로 꺼낼 수 도 있다!!

✏20240109 화요일

📖접두사인지 확인하기

  • startsWith 함수를 사용하여 is_prefix로 시작하는지 if문을 통해 확인하여 있으면 1 없으면 0을 반환
  • startsWith( ) : 특정 문자로 시작하는지 확인한다.
  • endsWith( ) : 특정문자로 끝나는지 확인한다.
class Solution {//나의 풀이
    fun solution(my_string: String, is_prefix: String): Int 
    = if(my_string.startsWith(is_prefix))1 else 0
}
  • 맨 처음에 for문으로 하나하나 잘라가면서 확인할까도 생각했었는데, 뭔가 비효율적인 것 같아서 검색했더니 startsWith이란 함수가 있었다. 사실 contains밖에 몰라서 맨 앞부터 포함해나가는걸 어떻게 표현해야하나 너무 당황스러웠던 것도 큰데, 이런 함수들은 정말 편리하고 좋은 것 같다.

📖접두사인지 확인하기 문제의 다른 사람 풀이

  1. class Solution {//다른 사람 풀이
        fun solution(myString: String, isPrefix: String): Int {
            return if (myString.indices
            	.map { myString.substring(0, it + 1) }
                .contains(isPrefix)) 1 else 0
        	}
    }
  • indices를 이용하여 문자열의 인덱스 it을 참조하는 map을 통해 substring으로 앞에서부터 잘라나가면서 isPrefix를 포함하고 있는지 확인하고 있으면 1 없으면 0을 반환한다.
  1. class Solution {//다른 사람 풀이
        fun solution(my_string: String, is_prefix: String): Int {
            var answer: Int = 0
            var check = ""
            my_string.forEach{
                check += it.toString()
                if(is_prefix == check) answer = 1
            }
            return answer
        }
    }
  • 확인을 위한 빈문자열 check를 만들고, my_string을 forEach로 반복하며 check에 앞에서부터 문자열 하나씩 더해가면서 is_prefix와 동일한 지확인하고 맞으면 1을 answer에 할당하여 반환한다.
  • 반복문을 통한 풀이도 가져와봤다. 1번같은경우는 문자열에도 indices를 쓰는게 새삼스러웠다. 문자열도 배열처럼 생각하는게 편하다고는 하지만 indices도 쓰이는게 뭔가 또 하나의 벽이 깨진 느낌.?ㅎ 2번 문제는.. 큰 차이는 없겠지만 forEach보다 for문 사용해서 찾은 후 break로 빠져나오는게 조금이라도 낫지 않았을까...? 아니면 중간에 찾아도 my_string 끝까지 계속 forEach도니까 굳이 그럴 필요 없을 것 같다.

📖홀수 vs 짝수

  • 홀수번째 요소와 짝수번째 요소를 합산할 변수 odd와 even을 선언했다.
  • for문을 통해 i가 num_list의 인덱스 범위만큼 반복하도록 indices를 사용하고, i가 짝수이면(인덱스번호는 0번부터시작하니까 첫번째요소를 인덱스0으로 판단했다.) odd에 합산하고 홀수이면 even에 합산되도록 if문을 작성했다.
  • maxOf를 사용하여 odd와 even 중에 더 큰 숫자를 반환한다.
class Solution {//나의 풀이
    fun solution(num_list: IntArray): Int {
        var odd = 0
        var even = 0
        
        for(i in num_list.indices){
            if(i % 2 == 0) odd += num_list[i]
            else even +=num_list[i]
        }
        
        return maxOf(odd,even)
    }
}
  • 처음에..ㅎ odd = num_list.filter{num_list.indexOf(it)%2 == 0}.sum() 라고 작성했는데, 첫번째 케이스만 유독 [4, 2, 6, 1, 7, 6] 중에서 [4, 6, 7, 6]를 반환해서.. 마지막 6은 도대체 뭐야? 다른 케이스들은 짝수 홀수 잘만 갈리던데.. 하고 제출 했더니 칼같이 실패 폭탄을 받고 그냥 얌전히 for문을 사용했다.
    => indexOf가 중복요소가 있을 땐, 해당 요소의 첫번째 인덱스 값을 반환 하기 때문에 안되는 거였다. filter에서 it이 한번씩 들어오니까 각각 판단해줄줄 알았는데. 아니였다. 칼같다. 앞에 num_list.indexOf(it)이라고 num_list를 붙여버리니까 it이 한번씩 들어와도 의미 없나 보다.

📖홀수 vs 짝수 문제의 다른 사람 풀이 : filterIndexed를 사용한 방법

class Solution {//다른 사람 풀이
   fun solution(num_list: IntArray): Int {
       var odd = num_list.filterIndexed { i, _ -> i % 2 != 0 }.sum()
       var even = num_list.filterIndexed { i, _ -> i % 2 == 0 }.sum()
       return if (odd > even) odd else even
   }
}
  • filterIndexed{index, i ->} : 인덱스와 요소를 함께 필터링 조건으로 사용할 수 있다.
  • 위의 코드에서는 람다식에서 인덱스는 사용하고 있지만, 요소에 대해서 사용하지 않고 있기 때문에 _를 표시하여 사용하지 않는 매개변술을 나타내고 있다.
  • num_list.indexOf(it) 이렇게 쓰는게 마음에 걸렸었었다. filterIndexed를 알고서 사용했었다면 머리 속에 그린 대로 문제를 풀 수 있었을텐데..ㅎ 이제라도 알았으니까 다음엔 바보같이 굴지 말아야겠다!

✏20240110 수요일

📖원하는 문자열 찾기

  • if문을 통해 contains로 pat이 대소문자를 무시한 pat이 myString에 포함되어있는지 확인하여 있으면 1 없으면 0을 반환했다.
class Solution {//나의 풀이
    fun solution(myString: String, pat: String): Int 
    = if(myString.contains(pat, true)) 1 else 0
}
  • contains(String, Boolean)
    : 문자열에 해당 String이 포함되는지 확인한다. Boolean값은 true일 경우 대소문자 구분을 무시하고, 작성하지 않을 경우 기본값은 false(대소문자 구분함)이다.
  • 맨 처음엔 어짜피 대소문자구분 무시니까 둘다 대문자(소문자)로 변경해서 비교할 생각도 했는데, 그건 뭔가 toUpper(Lower)Case를 반복한다는 점이 마음에 안들어서 좀 더 찾아보니까 contains로도 대소문자 구분 무시를 할 수 있다는 것을 알았다. contains에 boolean값을 매개변수로 받아주는지 자체를 이 문제를 통해 알았다. 유용하게 쓰일 것 같다.

📖개미 군단

  • 최소한의 병력을 데려갈 수 있게, 공격력이 제일 큰 5로 hp를 나눠준 후 나머지 값에 대해 다시 다음으로 공격력이 3으로 나눠서 그 몫과 나머지 값(공격력1) 을 다 더해주었다.
class Solution {//나의 풀이
    fun solution(hp: Int): Int {
        var a = hp/5
        var b = (hp - a*5)/3
        var c = (hp - a*5)%3
        
        return a + b + c
        
    }
}
  • 수학 공식 짜는거 왜이렇게 어려워 하는지... 너무 복잡하게 생각하는 경향이 있는지 중간에 5로 나눈 나머지 값이 3보다 크거나 같은 경우에 대한 if문을 작성했다가 또 꼬여서 다시 케이스 실패를 맛보고.. 다시 지우고.. 중복되는 부분을 최대한 지우고.. 하니까 저렇게 쉬운 문제였음을.. 사실 내가 쓴 풀이에도 b와 c값에 대해서 var b = hp % 5 / 3 var c = hp % 5 % 3를 사용했으면 더더 중복 없고 간결한 식이 되었을 텐데.. 라고 다른 사람 풀이를 보고 알았다. 굳이 일았으면 따로 변수도 사용안하고 그냥 = hp/5 + (hp%5)/3 + (hp%5%3)으로 뚝딱 풀었으면 될 것을.. 하여간 이런건 정말 많이 풀어보는 수밖에 없는 것 같다. 근데 이렇게 쉬운 문제도 이렇게 푼다는게 조금 슬플 뿐이다. ...

✏20240111 목요일

📖배열의 길이에 따라 다른 연산하기

  • arr에 대해 인덱스를 같이 요소로 사용하는 mapIndexed를 사용하여 arr.size%2로 홀수인지 짝수인지 판별하는 when으로 상황에 맞게 n을 더하는 코드를 작성 한 후 타입에 맞춰서 toIntArray( )를 사용했다.
class Solution {//나의 풀이
    fun solution(arr: IntArray, n: Int): IntArray 
    = arr.mapIndexed{idx,i ->
        when(arr.size%2) {
            0 -> if(idx%2!=0) i+n else i
            else -> if(idx%2 ==0) i+n else i
        }
    }.toIntArray()
}
  • 처음에 문제를 제대로 안..읽어서? 이해를 못해서 배열의 길이가 짝수이면 홀수인덱스값들만 +n해서 반환 하는 줄 알았다. 그래서 if문을 사용해서 else 없이 문제를 풀었더니 오류가 났다. else가 없어서 반환값을 어떻게 줘야할지 모르면 오류가 난다고 했다. when문으로 바꾼 후, 문제를 다시 읽고 +n해주지 않는 값들도 반환하고 나서야 통과를 받았다.

📖할 일 목록

  • todo_list에 대해 인덱스를 요소로 같이 사용하는 filterIndexed를 사용하여 finshed[idx]의 true/false 값을 판별하여 false인 것만 반환되도록 한 후, 타입을 맞춰주기 위해서 toTypedArray( )를 사용해줬다.
class Solution {//나의 풀이
    fun solution(todo_list: Array<String>, finished: BooleanArray): Array<String> 
    = todo_list.filterIndexed{idx, i -> !finished[idx]}.toTypedArray()

}
  • 마찬가지로 mapIndexed로 문제를 풀었다가 이번에야 말로 else에 쓸 게 없어서 오류를 맛보고 filterIndexed로 바꿔서 풀었더니 통과를 받았다. 바보 같이 조건문을 만나면 무조건 if문 쓸 생각부터 하는데, 긴지 아닌지 단순하게 따질 때 여러가지 방법을 활용하고 적용할 수 있도록 신경써야겠다.

✏20240112 금요일

📖배열의 원소만큼 추가하기

  • arr에 있는 원소 i 를 이중 for문을 통해 i만큼 answer에 추가되도록 작성한 후, answer를 반환했다.
class Solution {//나의 풀이
    fun solution(arr: IntArray): IntArray {
        var answer: IntArray = intArrayOf()
        
        for(i in arr){
            for(j in 1..i){
                answer += i
            }
        }
        
        return answer
    }
}

📖배열의 원소만큼 추가하기 문제의 다른 사람 풀이 : flatMap을 이용한 방법

class Solution {//다른 사람 풀이
    fun solution(arr: IntArray): List<Int> {
        return arr.flatMap { i -> List(i) { i } }
    }
}
  • flatMap을 사용하여 길이가 i이면서 요소가 i로 채워지도록 만든 리스트들을 단일리스트로 평면화 시켜서 반환시킨다.
  • flatMap : 감싸져있는 Collection을 하나로 합쳐서 배열(또는 iterable)을 반환한다.
    • Collection 내부에 Collection이 들어있는 경우, 내부의 Collection을 펼쳐준다.
    • map이 무조건 1:1 매핑이라면, flatMap은 1:1뿐만 아니라 1:다 매핑도 가능하다.
  • flatMap은 처음 보는 것 같은데, 찾아보니까 사용법이 되게 다양하게 있는 함수이다. 활용도가 높은.. 것 같은데 그만큼 복잡해서 지금 다루기에는 한 눈에 들어오지 않는다. 좀 더 많은 케이스를 배워야 할 것 같다.

📖최댓값 만들기 (2)

  • 이중 for문을 통해 배열의 요소들을 전부 서로 곱한 다음 arr에 추가해준다.
  • arr에서 가장 큰 값을 maxOf를 통해 반환한다.
class Solution {//나의 풀이
    fun solution(numbers: IntArray): Int {
        var arr = intArrayOf()

        for(i in numbers.indices){
            for(j in i+1 until numbers.size){
                arr += numbers[i]*numbers[j]
            }
        }

        return arr.maxOf{it}
    }
}
  • 원소 두개를 곱해서 최대값을 만드는 문제이기 때문에 맨 처음엔 numbers.sorted().takeLast(2).reduce{result, i -> result*i} 라고 코드를 적었다. 정렬해서 제일 큰 숫자 2개끼리 곱하면 되니까. 근데 이 배열에는 음수가 있기 때문에.. 음수끼리 곱하면 양수가 되니까.. 최대값이 꼭 맨 뒤에 값 2개 곱한다고 나오지가 않는 것이다...... 그래서 무슨 생각을 했냐면.. 아. 결국 다 곱한 값들 중에서 최대값을 찾아야 하네 라고 생각해서 이중 for문을 만들었다. 근데 이게 바보같았다는 것을 다른 사람 풀이 보고 알았는데... 어짜피 sorted( ) 하면 제일 작은 수부터 정렬하기 때문에 음수는 절댓값이 클수록 작은거니까 만약 음수 두개를 곱해서 최대값을 만들더라도 제일 앞의 두수만 곱하면 되는 거였다. 그니까 굳이 전부 다 곱해서 최대값을 찾지 않더라도, maxOf(numbers.sorted().take(2).reduce{result, i -> result*i}, numbers.sorted().takeLast(2).reduce{result, i -> result*i})를 통해서 최댓값을 구할 수 있던 거였지.ㅎ 반성의 의미로 기록하기 위해 가져왔다.
profile
파이팅!

0개의 댓글