프로그래머스 - 로또의 최고 순위와 최저 순위

프로그래머스 - 로또의 최고 순위와 최저 순위

프로그래머스 77484번 문제


아주 쉬운 문제다.

당첨 번호 대비 자신의 번호가 몇개 일치하는지를 알아내고, 이를 등수로 환산하면 최저 순위.

당첨 번호 대비 자신의 번호가 몇개 일치하는지를 알아내고 여기에 0의 개수를 더한 후, 이를 등수로 환산하면 나올 수 있는 최고 순위이다.

그대로 구현하기만 하면 된다.


@DisplayName("프로그래머스 77484 - 로또의 최고 순위와 최저 순위")
class Programmers77484Test {

    private Programmers77484 solve = new Programmers77484();

    private static Stream<Arguments> solution() {
        return Stream.of(
            Arguments.of(new int[]{44, 1, 0, 0, 31, 25}, new int[]{31, 10, 45, 1, 6, 19}, new int[]{3, 5}),
            Arguments.of(new int[]{0, 0, 0, 0, 0, 0}, new int[]{38, 19, 20, 40, 15, 25}, new int[]{1, 6}),
            Arguments.of(new int[]{45, 4, 35, 20, 3, 9}, new int[]{20, 9, 3, 45, 4, 35}, new int[]{1, 1})
        );
    }

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

}


처음엔 enum을 사용해 구현했다.

enum 내부에 Map 등을 사용하면 더 최적화가 되긴 했겠지만, 이정도 수준에서는 유의미한 차이를 내기 힘들 것 같았다. (귀찮았다…)


public class Programmers77484 {

    public int[] solution(int[] lottos, int[] winNums) {
        long countOfZero = Arrays.stream(lottos)
            .filter(num -> num == 0)
            .count();

        long matchCount = Arrays.stream(winNums)
            .filter(winNum -> Arrays.stream(lottos)
                .anyMatch(lotto -> winNum == lotto))
            .count();

        return new int[]{
            MatchPrize.findRankByMatchCount((int) (matchCount + countOfZero)),
            MatchPrize.findRankByMatchCount((int) matchCount)
        };
    }

    private enum MatchPrize {
        FIRST(1, 6),
        SECOND(2, 5),
        THIRD(3, 4),
        FOURTH(4, 3),
        FIFTH(5, 2),
        SIXTH(6, 1);

        private final int rank;
        private final int matchCount;

        MatchPrize(int rank, int matchCount) {
            this.rank = rank;
            this.matchCount = matchCount;
        }

        private static int findRankByMatchCount(int matchCount) {
            return Arrays.stream(values())
                .filter(matchPrize -> matchPrize.matchCount == matchCount)
                .findFirst()
                .orElse(SIXTH)
                .rank;
        }

    }

}


이러고 나서 보니 코드가 너무 장황하지 않나? 라는 느낌이 들었다.


public class Programmers77484 {

    private static final int[] RANK = {6, 6, 5, 4, 3, 2, 1};

    public int[] solution(int[] lottos, int[] winNums) {
        Set<Integer> lottoSet = stream(lottos)
            .boxed()
            .collect(Collectors.toUnmodifiableSet());

        int countOfZero = (int) stream(lottos)
            .filter(this::isZero)
            .count();

        int matchCount = (int) stream(winNums)
            .filter(lottoSet::contains)
            .count();

        return new int[]{RANK[countOfZero + matchCount], RANK[matchCount]};
    }

    private boolean isZero(int num) {
        return num == 0;
    }

}


코드가 훨씬 간결해지긴 했는데, 가독성이나 확장성 측면에서는 이전 코드가 좀 더 좋다는 느낌이 든다.

이런 미묘한 고민들이 항상 어려운 것 같다.



© 2022. All rights reserved.