Coding Test/Programmers

[Lv.1] 로또의 최고 순위와 최저 순위 [프로그래머스_코딩테스트] [수학, 시뮬레이션] [30분] [2021 Dev-Matching: 웹 백엔드 개발자(상반기)]

whawoo 2025. 6. 14. 09:27
반응형

🔍 문제 요약

https://school.programmers.co.kr/learn/courses/30/lessons/77484

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

로또(1~45)의 숫자를 6개 선택을 하고 몇개가 지워져서 0으로 들어간 상태일 때, 로또 번호 win_nums 배열이 주어지고 맞춘 개수에 따라 가능한 최고 순위와 최저 순위를 구하는 문제

🧠 나의 접근 방식과 시행착오

16분 정도 걸린 문제. 간단하게 맞춘 개수와 등수를 Dictionary로 매핑을 한 후 lottos와 win_nums에 중복되는 숫자를 Array를 활용해서 계산하여 최저 등수를 구했다. 그리고 0의 개수를 체크하여 다 맞춘 개수라고 했을 때를 가정하여 최대 등수를 가져오는 방식을 사용하였다.

using System;
using System.Collections.Generic;

public class Solution
{
    /// <summary>
    /// 로또의 최고 순위와 최저 순위
    /// https://school.programmers.co.kr/learn/courses/30/lessons/77484
    /// </summary>
    public int[] solution(int[] lottos, int[] win_nums)
    {
        // 당첨 번호 배열 win_nums
        // 선택한 로또 번호 lottos
        // 일단 둘 간의 중복된 숫자로 최저 순위 번호를 찾아야 함
        // 6개 - 1등
        // 5개 - 2등
        // 4개 - 3등
        // 3개 - 4등
        // 2개 - 5등
        // 그 이하 - 6등
        var calcDict = new Dictionary<int, int>()
        {
            { 6, 1 },
            { 5, 2 },
            { 4, 3 },
            {3, 4},
            {2, 5},
            {1, 6},
            {0, 6},
        };
        
        var nums = Array.FindAll(lottos, (a) => Array.Exists(win_nums, (b) => b == a));
        
        // 최저 순위
        int minScore = calcDict[nums.Length];
        
        // 최고 순위 구하기 : 중복된 숫자 개수 + 0의 개수
        var zeroArr = Array.FindAll(lottos, (a) => a == 0);
        int zeroCount = zeroArr.Length;
        
        int maxScore = calcDict[nums.Length + zeroCount];
        
        int[] answer = new int[2] {maxScore, minScore};
        return answer;
    }
}

/// <summary>
/// C# 7.3
/// </summary>
internal class Program
{
    public static void Main(string[] args)
    {
        var sl = new Solution();
        var lottos1 = new[] { 44, 1, 0, 0, 31, 25 };
        var win_nums1 = new[] { 31, 10, 45, 1, 6, 19 };
        var res1 = sl.solution(lottos1, win_nums1);
        var lottos2 = new[] { 0, 0, 0, 0, 0, 0 };
        var win_nums2 = new[] { 38, 19, 20, 40, 15, 25 };
        var res2 = sl.solution(lottos2, win_nums2);
        var lottos3 = new[] { 45, 4, 35, 20, 3, 9 };
        var win_nums3 = new[] { 20, 9, 3, 45, 4, 35 };
        var res3 = sl.solution(lottos3, win_nums3);
        
        Console.WriteLine($"{res1[0]}, {res1[1]}");
        Console.WriteLine($"{res2[0]}, {res2[1]}");
        Console.WriteLine($"{res3[0]}, {res3[1]}");
    }
}

✅ 풀이 코드

피드백으로 받은 부분은 Array.FindAll과 그 안의 Array.Exist의 성능의 문제 (개수가 고저되어 있고 크지 않아서 사실 큰 상관은 없지 않나 싶긴 하다만..) HashSet으로 개선 방향에 대해서 추천해주었다. 또한 점수를 매기는 것도 Dictionary로 매핑을 하는 것도 직관적이지만 피드백을 받은 코드에서는 내부 함수를 한 후 규칙에 따라서 등수를 계산해내는 형태로 구현을 하였다. (개인적인 생각으로는 직관성이나 나중의 변경이 가능한 라이브 서비스에서라면 좋은 방향으로 보이진 않다는 생각이 들었다.)

public int[] solution(int[] lottos, int[] win_nums)
{
    var winSet = new HashSet<int>(win_nums);

    int zeroCount = 0;
    int matchedCount = 0;

    foreach (var num in lottos)
    {
        if (num == 0)
            zeroCount++;
        else if (winSet.Contains(num))
            matchedCount++;
    }

    int maxMatched = matchedCount + zeroCount;
    int minMatched = matchedCount;

    int rank(int matched) => matched >= 2 ? 7 - matched : 6;

    return new[] { rank(maxMatched), rank(minMatched) };
}

🔄 정리

푸는 방법적인 부분이 있겠지만 자주 사용을 하지 않았던 HashSet도 차츰 공부를 해서 활용을 해볼 수 있게 연습하기를 추천

반응형