JAVA - 프로그래머스 2레벨 - 위장

JAVA - 프로그래머스 2레벨 - 위장

프로그래머스 42578번 문제


image


@DisplayName("프로그래머스 42578 - 위장")
class Programmers42578Test {
    Programmers42578 solve = new Programmers42578();

    static Stream<Arguments> solution() {
        return Stream.of(
            Arguments.of(new String[][]{
                {"yellowhat", "headgear"}, {"bluesunglasses", "eyewear"}, {"green_turban", "headgear"}
            }, 5),
            Arguments.of(new String[][]{
                {"crowmask", "face"}, {"bluesunglasses", "face"}, {"smoky_makeup", "face"}
            }, 3)
        );
    }

    @MethodSource
    @ParameterizedTest
    void solution(String[][] clothes, int expected) throws Exception {
        int actual = solve.solution(clothes);
        assertThat(actual).isEqualTo(expected);
    }
}


해쉬맵과 경우의 수를 사용해서 풀 수 있다.


첫번째 케이스를 보자.

  • headgear: yellowhat, green_turban
  • eyewear: bluesunglasses


스파이는 하루에 최소 한 개의 의상을 입습니다.


즉, eyewearbluesunglasses를 착용했다면, headgear는 아예 착용하지 않을수도 있다.

하지만, 반드시 한개는 착용해야 하므로 headgear와 eyewear 모두를 착용하지 않을수는 없다.

한마디로 의상을 착용하지 않는 경우를 고려해 전체 경우의 수를 구한 후, 모든 의상을 착용하지 않는(맨몸) 경우 단 한가지만 제외해주면 답이 나온다.

위 케이스에서 식은 다음과 같다.

(headgear의 갯수 + 1(=headgear를 아예 착용하지 않는 경우)) * (eyewear의 갯수 + 1(=eyewear를 아예 착용하지 않는 경우)) - 1(맨몸인 경우)

(2 + 1) * (1 + 1) - 1 = 5

두번째 케이스도 같은 답이 도출된다.

  • face: crowmask, bluesunglasses, smoky_makeup

(3 + 1) - 1 = 3


대체로 PS가 대체로 실무에서 푸는 현실세계의 문제와 무관하면서도 막상 명령형으로 풀고보면 코드도 마음에 안드는게 불편했었다.

왜냐하면 PS에서 제출하는 답안은 패키지 개념이 없어 하나의 파일에 여러개의 TOP 클래스를 작성해야하기 때문이다.

이는 유지보수 관점에서도 좋지 않고, 자바 관례에도 어긋나며, 접근제한자 사용에도 제약이 따른다.


요즘 실무에 비동기를 적용해보고 모르는걸 공부하면서 자연스레 FP에 대해 관심이 높아졌는데 이 FP를 연습하는데 PS가 생각보다 도움이 꽤 되는 것 같다.

애초에 FP자체가 수학에서 출발해서 그런지, 수학익힘책 느낌이 나는 PS에 적용하기가 아주 적절하다.


잡설이 좀 있었는데, 구현은 다음과 같다.

인자로 넘어오는 2차원 배열 clothes를 1차원 배열로 풀어헤쳐놓고 보면 0번 인덱스는 의상이고 1번 인덱스는 옷의 카테고리다.

즉, 자바의 스트림을 이용해 1번 인덱스를 키로 그루핑하고 0번 인덱스의 합계를 값으로 매핑하면 적절한 해쉬맵이 만들어진다.

이후 reduce 함수를 사용해 모든 값(옷 카테고리의 갯수)을 위의 식대로 누산해준다.

마지막으로 옷을 아예 입지 않는 맨몸인 경우의 수 1개를 빼주면 답이 나온다.


public class Programmers42578 {
    public int solution(String[][] clothes) {
        return stream(clothes)
            .collect(groupingBy(clothe -> clothe[1], mapping(clothe -> clothe[0], counting())))
            .values()
            .stream()
            .reduce(1L, (answer, numberOfClothes) -> answer * (numberOfClothes + 1))
            .intValue() - 1;
    }
}


FP를 잘 익혀두면 우선 비동기, 멀티스레딩이나 근 미래에 사용하게 될 웹플럭스에 도움이 될 것 같다고 생각한다.

그러면서도 이 미래 먹거리를 아무런 리스크 없이, 따분함도 풀어가면서 익히기에 PS만한게 사실 없는 것 같다.

애초에 PS자체가 실무에 아무런 도움이 안된다는 주의였는데, FP를 이렇게 편하게 연습할 수 있다는건 좋은 것 같다.



© 2022. All rights reserved.