[Lv.1] 로또의 최고 순위와 최저 순위 [프로그래머스_코딩테스트] [수학, 시뮬레이션] [30분] [2021 Dev-Matching: 웹 백엔드 개발자(상반기)]
🔍 문제 요약
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도 차츰 공부를 해서 활용을 해볼 수 있게 연습하기를 추천