TIL/알고리즘

04/12 알고리즘 공부(90) - 의상

sos000303 2024. 4. 12. 09:44
728x90

조건

코니는 매일 다른 옷을 조합하여 입는것을 좋아합니다.

예를 들어 코니가 가진 옷이 아래와 같고, 오늘 코니가 동그란 안경, 긴 코트, 파란색 티셔츠를 입었다면 다음날은 청바지를 추가로 입거나 동그란 안경 대신 검정 선글라스를 착용하거나 해야합니다.

종류이름

얼굴 동그란 안경, 검정 선글라스
상의 파란색 티셔츠
하의 청바지
겉옷 긴 코트
  • 코니는 각 종류별로 최대 1가지 의상만 착용할 수 있습니다. 예를 들어 위 예시의 경우 동그란 안경과 검정 선글라스를 동시에 착용할 수는 없습니다.
  • 착용한 의상의 일부가 겹치더라도, 다른 의상이 겹치지 않거나, 혹은 의상을 추가로 더 착용한 경우에는 서로 다른 방법으로 옷을 착용한 것으로 계산합니다.
  • 코니는 하루에 최소 한 개의 의상은 입습니다.

코니가 가진 의상들이 담긴 2차원 배열 clothes가 주어질 때 서로 다른 옷의 조합의 수를 return 하도록 solution 함수를 작성해주세요.

제한조건

  • clothes의 각 행은 [의상의 이름, 의상의 종류]로 이루어져 있습니다.
  • 코니가 가진 의상의 수는 1개 이상 30개 이하입니다.
  • 같은 이름을 가진 의상은 존재하지 않습니다.
  • clothes의 모든 원소는 문자열로 이루어져 있습니다.
  • 모든 문자열의 길이는 1 이상 20 이하인 자연수이고 알파벳 소문자 또는 '_' 로만 이루어져 있습니다.

입출력 예

clothes return
[["yellow_hat", "headgear"], ["blue_sunglasses", "eyewear"], ["green_turban", "headgear"]] 5
[["crow_mask", "face"], ["blue_sunglasses", "face"], ["smoky_makeup", "face"]] 3

알고리즘 예상

  1. 종류에 맞춰서 그룹화 한 다음 각 그룹의 원소 크기 + 1의 곱을 answer에 저장한다.
  2. 아무것도 입지 않는 1을 빼면 총 종류가 나올 것으로 예상된다.

 

초기 코드

class Solution {
    fun solution(clothes: Array<Array<String>>): Int {
        var answer = 0
        return answer
    }
}

 

내 코드

//성공
class Solution {
    fun solution(clothes: Array<Array<String>>): Int {
        var answer = 1
        val clothesGroup = clothes.groupBy { it[1] }

        for (i in clothesGroup) {
            answer *= i.value.size + 1
        }
        answer -= 1
        
        return answer
    }
}

 

다른 사람의 풀이

class Solution {
    fun solution(clothes: Array<Array<String>>): Int {
        return clothes.groupBy { it[1] }.values.fold(1) { acc, v -> acc * (v.size + 1) }  - 1
    }
}
class Solution {
    fun solution(clothes: Array<Array<String>>) = clothes
        .groupBy { it[1] }.values   // group by type of clothes, keep only names of clothes
        .map { it.size + 1 }        // number of things to wear in a group (including wearing nothing)
        .reduce(Int::times)         // combine
        .minus(1)                   // remove the case where the spy wears nothing
}

개선점 또는 배운점

  1. 풀이 대부분이 로직은 비슷하게 사용했다. 
  2. 아래 풀이에서 사용한 reduce는 fold와 비슷하게 동작하지만 초기값을 지정해야하는 fold와는 달리 해당 배열의 첫 요소를 초기값으로 자동으로 지정해준다. 소괄호 내부에 자료형과 값을 접을 때 사용할 연산을 넣을 수 있다. 기본값은 더하기이다. 다만 해당 연산은 첫 요소에는 적용되지 않기 때문에 요소*2의 합 등을 구할 때 첫 요소의 값은 2배가 적용되지 않고 연산된다.

 

개선된 코드

class Solution {
    fun solution(clothes: Array<Array<String>>): Int {
        return clothes.groupBy { it[1] }.values.fold(1) { acc, v -> acc * (v.size + 1) }  - 1
    }
}
728x90