본문 바로가기

알고리즘/프로그래머스

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

문제 내용

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

 

코딩테스트 연습 - 로또의 최고 순위와 최저 순위

로또 6/45(이하 '로또'로 표기)는 1부터 45까지의 숫자 중 6개를 찍어서 맞히는 대표적인 복권입니다. 아래는 로또의 순위를 정하는 방식입니다. 1 순위 당첨 내용 1 6개 번호가 모두 일치 2 5개 번호

programmers.co.kr

내가쓴 로또 번호(int[] lottos)와 1등 번호(int[] win_nums)를 비교해서 최고와 최저 순위를 구하는 방식이다.

조건은 내가쓴 로또 번호에서 0으로 표기된건 로또번호 1~45 숫자 중 중복되지 않는선에서 어느것으로든 바꿀수 있다는 조건이 있는 문제이다.

 


문제 접근 방법

문제는 두가지 방식으로 풀었다.

 

첫번째는 최고순위를 구할 땐 주어진 lottos 배열과 win_nums 배열만큼 돌면서 일치여부 확인 후 0인것 들을 win_nums중 lottos번호에 없는것을 뽑아 넣어주고 등수를 구하고,

최저순위를 구할 땐  lottos 배열과 win_nums 배열만큼 돌면서 일치여부 확인 후 0인것 들에 1~45까지 난수를 발생시켜 win_nums에 없는 것을 넣어주는 방식으로 풀었다. 

 

첫번째 방법으로 풀고 다른사람 풀이들을 보면서 현타온 후 그중 맘에드는 풀이로 다시한번 풀어봤다.

 

 

 

두번째 방법은 HashMap을 이용하는 방법이다.

key로는 lottos배열에 0이 아닌 값을, value값을 넣어준다. 그리고 0은 몇개인지 세어준다.

그리고 win_nums 배열 요소하나씩 꺼내면서 HashMap에 key값으로 win_nums배열 요소가 있는지 없는지 확인하면서 세어준다.

 

마지막으로 최고와 최저등수를 구해준다.

 

아래서 한번 보자~

 


 

풀이

첫번째 방법

	public static int[] my_solution(int[] lottos, int[] win_nums) {
		int[] answer = new int[2];
		int[] copy=lottos.clone();
		Random rd = new Random();
		int cnt = 0; //번호일치하는 수
		int ans = 0; //등수
		
		//최고등수 구하기
		for (int i = 0; i < lottos.length; i++) {
			for (int j = 0; j < win_nums.length; j++) {
				if(lottos[i]==0) {
					lottos[i]=win_nums[j];
				}
				if(lottos[i] == win_nums[j]) {
					cnt++;
				}
			}
		}
		
		if(cnt==0) {
			ans = 6;
			answer[0]=ans;
		}else {
			ans = 7-cnt;
			answer[0]=ans;
		}
		cnt = 0;
		ans = 0;
		
		//최저등수 구하기
		for(int i=0; i<copy.length; i++) {
			for(int j=0; j<win_nums.length; j++) {
				if(copy[i]==0) {
					boolean check = true;
					boolean check2 = true;
					//temp값이 lottos 배열과 win_nums배열 모두에 일치하는게 없을때 copy[i]에 temp 넣어줌
					while(check || check2) { 
						int temp = rd.nextInt(45)+1;
						copy[i] = temp;
						check = IntStream.of(win_nums).anyMatch(x -> x==temp);
						check2 = IntStream.of(copy).anyMatch(x -> x==temp);
					}
				}
				if(copy[i]==win_nums[j]) {
					cnt++;
				}
			}
		}
		
		if(cnt==0) {
			ans = 6;
			answer[1]=ans;
		}else {
			ans = 7-cnt;
			answer[1]=ans;
		}
		
		return answer;
	}

 

보다시피 코드의 길이가 길어지고 코드를 읽는데 좋지 않다고 느껴진다

두번재 풀이를 보자

 


두번째 방법

public static int[] other_solution(int[] lottos, int[] win_nums) {
		HashMap<Integer, Boolean> map = new HashMap<Integer, Boolean>();
		int zeroCnt = 0;
		int sameCnt = 0;
		
		for(int num:lottos) {
			if(num==0) {
				zeroCnt++;
				continue;
			}
			map.put(num, true);
		}
		
		for(int wNum:win_nums) {
			if(map.containsKey(wNum)) sameCnt++;
		}
		
		int maxRank = 7-(zeroCnt+sameCnt);
		int minRank = 7-(sameCnt);
		if(maxRank>6) maxRank=6;
		if(minRank>6) minRank=6;
		
		return new int[] {maxRank, minRank};
	}

보다시피 코드도 짧아지고 실제로 돌렸을때 효율이 훨씬 좋다.

그리고 여기선 value값을 Boolean으로 설정하고 넣어줬지만 사실 이코드는 key값이 중요한거라

value값은 Integer로 하든 Boolean으로 하든 뭐로하든 상관없다고 생각한다.

 


마치며

프로그래머스에서 레벨1문제로 분류되긴 했지만 그래도 문자관련 문제를 많이 안다뤄본 나에겐 좋은 공부가 됐다.