2022 우테코에서 진행하는 공개된 사전과제 코딩테스트 문제 입니다.
https://github.com/Backcoder-June/java-lotto
GitHub - Backcoder-June/java-lotto: 로또 미션을 진행하는 저장소
로또 미션을 진행하는 저장소. Contribute to Backcoder-June/java-lotto development by creating an account on GitHub.
github.com
( 상세한 문제 설명은 링크를 타고 들어가서 확인해주세요! )
Lotto Application
로또 프로그램을 Console 에서 구현해 보는 미션이었습니다.
전체적으로 제한사항 및 요구사항이 많았고, 자료구조를 다양하게 활용해 볼 수 있어서 많은 도움이 됬던 과제였습니다.
=> 메소드 당, 15라인 이내에서 작은 기능 단위별로 구분하고, 이를 적절하게 연결하여 프로그램을 만들 수 있는가
=> 사용자의 입력값을 받아, 기능별로 적절한 자료구조를 활용할 수 있는가
=> 자료구조를 sort 정렬하는 다양한 방법에 대한 이해
=> RegEx, Exception 을 통해 상황에 따른 ERROR 처리를 할 수 있는가
이번 우테코 과제에서는
전체적으로 메소드들을 최대한 작은 단위로 짤라서 구현하게끔 유도해주었는데 ( 메소드 별 Max 15 Lines 제한 )
이 과정에서
기능별로 나누는 포인트를 잡는 법,
나눠진 메소드들을 효율적으로 연결 하는 법,
만들어 둔 메소드를 다른 기능에 재활용 하는 법,
전체적 흐름을 코드 라인을 따라가면서 파악하는게 아니라
method 흐름을 따라가면서 파악하는 법
등등, 확실히 많은 부분을 배울 수 있었고, 왜 그렇게 객체지향을 추구해야 하는지 다시한번 생각하게 되었습니다.
[ 구현 Methods ]
(1) 기본 주어진 Lotto class 및 validate 활용
- Lotto 클래스가 기본적으로 List<Integer> numbers 를 가지고있고, validate 까지 실행시키고 있다.
=> 즉 랜덤한 로또번호를 만들고, 그 값으로 Lotto 클래스를 생성하면 validate 까지 시켜주게 된다.
validate 메소드에는 프로그램 오류로 발생할 수 있는 ERROR 들을 추가해 주었다.
public class Lotto {
private final List<Integer> numbers;
public Lotto(List<Integer> numbers) {
validate(numbers);
this.numbers = numbers;
}
private void validate(List<Integer> numbers) {
if (numbers.size() != 6) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 총 6개를 입력해야 합니다.");
}
if (numbers.size() == 6 && convertListToSet(numbers).size() != 6) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 중복될 수 없습니다.");
}
for (Integer eachNum:numbers
) {
if (eachNum < 1 || 45 < eachNum) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}
}
}
(2) 로또번호 생성 및 Sort 정렬
- 주어진 Randoms 메소드를 이용해 Lotto 클래스를 생성한다.
=> 순서가 랜덤하게 되어있다.
- API 에서는 Collections.sort 등을 활용하면 정렬되고 눈에 보이는 오류 없이 실행이 되었다.
하지만 testCode 를 돌려보면 Collections.sort 부분에서 UnsupportedOperationException 이 발생하며 실패했다.
주로 List 형을 new로 초기화하지 않는 상태에서 생성하였을 시 발생한다고 하는데,
new ArrayList 로 리스트를 생성한게 아니라, new Lotto로 생성하면서 발생하는 문제인 듯 하다.
=> TreeSet 을 이용하는 방법을 택했다.
직접적으로 lotto의 데이터에 손을대고 sort 하는게 아니라, 그저 TreeSet에 담을 뿐,
TreeSet에는 자동으로 정렬되며 담기기 때문에 sort 를 사용하지 않아도 된다.
public static List<Lotto> getLottoNum(Integer lottoCount){
List<Lotto> lottoNumList = new ArrayList<>();
for (int i = 0; i < lottoCount; i++) {
Lotto lotto = new Lotto(Randoms.pickUniqueNumbersInRange(1, 45, 6));
Set sortedLotto = lotto.sortLottoNum(lotto);
lottoNumList.add(lotto);
System.out.println(sortedLotto);
}
return lottoNumList;
}
public Set sortLottoNum(Lotto lotto) {
Set sortingSet = new TreeSet();
for (Integer eachNum:lotto.numbers
) {
sortingSet.add(eachNum);
}
return sortingSet;
}
(3) 적절한 자료구조를 사용하기 위한 convert 메소드들
- 기능별로, 자료구조들을 List - Set - Map 등을 바꿔가며 사용해야 했다.
=> 필요한 자료구조 변환을 메소드로 만들어 두고 사용한다.
public static Set<Integer> convertStringToIntegerSet(String winningNumbers){
String[] split = winningNumbers.split(",");
Set<Integer> IntegerSet = new HashSet<>();
for (int i = 0; i < split.length; i++) {
IntegerSet.add(Integer.parseInt(split[i]));
}
return IntegerSet;
}
public static List<Set<Integer>> convertLottoToIntegerSet(List<Lotto> lottoList) {
List<Set<Integer>> LottoNumSetList = new ArrayList<>();
for (int i = 0; i < lottoList.size(); i++) {
Set<Integer> LottoNumSet = new HashSet<>();
List<Integer> lottoNums = lottoList.get(i).numbers;
for (Integer lottoNum:lottoNums
) {
LottoNumSet.add(lottoNum);
}
LottoNumSetList.add(LottoNumSet);
}
return LottoNumSetList;
}
public static List<Integer> convertSetToList(Set<Integer> lottoList) {
List<Integer> tempList = new ArrayList<>();
for (Integer lottoNum:lottoList
) {
tempList.add(lottoNum);
}
return tempList;
}
public static Set<Integer> convertListToSet(List<Integer> lottoList) {
Set<Integer> tempSet = new HashSet<>();
for (Integer lottoNum:lottoList
) {
tempSet.add(lottoNum);
}
return tempSet;
}
(4) 맞춘 로또 개수 Count && 맞춘 로또 개수 별 Count
- 핵심 로직부분이 아닐까 한다.
- List 로 돌리면서 확인하기엔 코드도 복잡하고 for 문을 여러번 돌아야 할 것으로 판단,
=> Set 의 retainAll 을 사용했다.
- retainAll 을 해준 뒤 Set 의 Size 는 matching 된 개수를 의미한다.
- 5개를 맞췄을 경우, bonusNum 에 대한 여부를 확인해야 하므로,
로직을 추가해 5개를 맞추고 보너스까지 맞췄을 경우 임의적 수 7을 넣어두고 후에 처리한다.
=> 여기서, 처음에 777 을 줬는데 후처리를 할 때, 분명 777 리스트에 넣어둔 777과 keySet의 777이 일치하는데도
boolean 에서 false 가 나서 시간을 꽤나 잡아먹혔다.
=> .byteValue 를 이용해서 비교하니 제대로 작동했고, 7로 바꾸니 boolean 작동이 정상적으로 됬다.
프로그램에서 숫자가 커지면서 생기는 0.00 소수점 아래의 문제가 아닐까 한다.
- 맞춘 개수별로, map 을 이용해 3 - 몇개 / 4 - 몇개 / .. / 7 - 몇개 하는 식으로 저장해 두고 이를 리턴해서 수익률 계산할 때 사용했다. 7을 5등 + 보너스 로 후처리 해주면 된다.
public static List<Integer> getMatchingCount(List<Set<Integer>> lottoList, Set<Integer> winningNumbers, int bonusNum) {
List<Integer> matchingCountList = new ArrayList<>();
for (int i = 0; i < lottoList.size(); i++) {
List<Integer> tempList = convertSetToList(lottoList.get(i));
Set<Integer> LottoNumSet = lottoList.get(i);
LottoNumSet.retainAll(winningNumbers);
if (LottoNumSet.size() == 5 && tempList.contains(bonusNum)) {
matchingCountList.add(7);
continue;
}
matchingCountList.add(LottoNumSet.size());
}
return matchingCountList;
}
public static Map<Integer,Integer> getMatchingCountNumber(List<Integer> matchingCountList) {
Map<Integer, Integer> matchingCount_Number = new HashMap<>();
for (int i = 0; i < 4; i++) {
matchingCount_Number.put(i + 3, 0);
}
matchingCount_Number.put(7, 0);
for (int j = 0; j < matchingCountList.size(); j++) {
for (Integer keySet:matchingCount_Number.keySet()) {
if (matchingCountList.get(j)>=3 && matchingCountList.get(j) == keySet) {
matchingCount_Number.put(keySet, matchingCount_Number.get(keySet) + 1);
}
}
}
return matchingCount_Number;
}
(5) 수익률 계산 및 enum 활용
- map 에 등수 별 개수가 들어있으니 수익률 계산은 간단하지만,
등수 별 => 상금 등 대응 관계가 있는 부분이라 enum 을 사용하기에 적절해 보여서 약간 억지로 enum 을 써보기 위해 코드를 고쳤다.
- 쓰고 나서도, ' enum 그렇게 쓰는거 아닌데~ ' 싶다. 아직은 익숙하지 않으니 사용법을 더 숙지해야 겠다.
- 수익률은 소수점 첫째자리까지 반올림하여 나타내줘야 하고, 정수 부분은 , 쉼표처리 해주기 위해
DecimalFormat 을 이용했다.
=> 수익률이 없을 경우, 혹은 소수점 자리가 없을 경우 0.0% 등으로 표시되어야 하므로 마지막 두자리는 0 으로 format
public enum matching {
THREE(3, 5000),
FOUR(4, 50000),
FIVE(5, 1500000),
SIX(6, 2000000000),
BONUS(7, 3000000);
private final int count, value;
private matching(int count, int value) {
this.count = count;
this.value = value;
}
public int getCount() {
return this.count;
}
public int getValue() {
return this.value;
}
}
public static String getBenefit(Map<Integer, Integer> matchingCountNum, String price) {
double totalPrice = 0;
for (Integer matchingCount:matchingCountNum.keySet()
) {
if (matchingCountNum.get(matchingCount) != 0) {
if (matching.THREE.getCount() == matchingCount) {totalPrice += matching.THREE.getValue() * matchingCountNum.get(matchingCount);}
if (matching.FOUR.getCount() == matchingCount) {totalPrice += matching.FOUR.getValue() * matchingCountNum.get(matchingCount);}
if (matching.FIVE.getCount() == matchingCount) {totalPrice += matching.FIVE.getValue() * matchingCountNum.get(matchingCount);}
if (matching.SIX.getCount() == matchingCount) {totalPrice += matching.SIX.getValue() * matchingCountNum.get(matchingCount);}
if (matching.BONUS.getCount() == matchingCount) {totalPrice += matching.BONUS.getValue() * matchingCountNum.get(matchingCount);}
}
}
return new DecimalFormat("###,##0.0").format((totalPrice/Integer.parseInt(price))*100);
}
출력할 메세지는 StringBuilder 에 담아서 return 해주었다.
public static StringBuilder convertMatchingInfoToMessage(Map<Integer, Integer> matchingCountNumber) {
StringBuilder sb = new StringBuilder();
sb.append("3개 일치 (5,000원) - ");
sb.append(matchingCountNumber.get(3) + "개\n");
sb.append("4개 일치 (50,000원) - ");
sb.append(matchingCountNumber.get(4) + "개\n");
sb.append("5개 일치 (1,500,000원) - ");
sb.append(matchingCountNumber.get(5) + "개\n");
sb.append("5개 일치, 보너스 볼 일치 (30,000,000원) - ");
sb.append(matchingCountNumber.get(7) + "개\n");
sb.append("6개 일치 (2,000,000,000원) - ");
sb.append(matchingCountNumber.get(6) + "개");
return sb;
}
(6) ERROR Handle
- 사용자의 입력값을 받기 때문에, 발생할 수 있는 에러의 종류가 다양하다.
=> RegEx 를 이용해 대부분의 에러를 잡는다.
=> RegEx 로 걸러지지 못한 Exception ( 중복, 범위 등 ) 에 대해 처리한다.
- RegEx 에 많이 숙달이 되면, 중복이나 범위 등에 대한 에러도 RegEx로 처리할 수 있을 듯 하다.
- 메소드에서 throw new Exception 으로 에러를 던져놓고,
main 실행 API 에서 try-catch 로 잡으면서 e.getMessage 를 System.out 해주면 문제에서 요구하는 대로
[ERROR] 로 시작하는 내가 지정해둔 메세지만이 출력된다.
public static void priceValidator(String price) {
if (!price.matches("[\\d]{1,8}")) {
throw new IllegalArgumentException("[ERROR] 1억 이하의 숫자만 입력 가능합니다. (1000원 단위)");
}
if (Integer.parseInt(price) % 1000 != 0 || price.equals("0")) {
throw new IllegalArgumentException("[ERROR] 구입은 1000원 단위로만 가능합니다.");
}
}
public static void winningNumFormatValidator(String winningNum) {
if (!winningNum.matches("[0-9]{1,2},[0-9]{1,2},[0-9]{1,2},[0-9]{1,2},[0-9]{1,2},[0-9]{1,2}")) {
throw new IllegalArgumentException("[ERROR] 당첨번호는 숫자,숫자,숫자... 형식으로 6개를 입력해주세요. ex)1,2,3,4,5,6");
}
}
public static void winningNumValidator(Set<Integer> winningNumSet) {
if (winningNumSet.size() != 6) {
throw new IllegalArgumentException("[ERROR] 당첨번호는 중복될 수 없습니다.");
}
for (Integer winnigNum:winningNumSet
) {
if (winnigNum < 0 || 45 < winnigNum) {
throw new IllegalArgumentException("[ERROR] 당첨번호는 1 ~ 45 사이의 숫자여야 합니다.");
}
}
}
public static void bonusNumValidator(String bonusNum, Set<Integer> winningNumSet) {
if (!bonusNum.matches("[0-9]{1,2}")) {
throw new IllegalArgumentException("[ERROR] 한 개의 숫자만 입력해 주세요.(1-45)");
}
if (Integer.parseInt(bonusNum) < 0 || 45 < Integer.parseInt(bonusNum)) {
throw new IllegalArgumentException("[ERROR] 1~45 사이의 숫자만 가능합니다.");
}
if (winningNumSet.contains(Integer.parseInt(bonusNum))) {
throw new IllegalArgumentException("[ERROR] 보너스 번호는 당첨번호와 중복될 수 없습니다.");
}
}
[ 실행 API ]
package UTEKO.ThirdWeek.lotto;
import camp.nextstep.edu.missionutils.Console;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Application {
public static void main(String[] args) {
// TODO: 프로그램 구현
try {
System.out.println("구입할 금액을 입력해주세요.");
String price = Console.readLine();
Lotto.priceValidator(price);
Integer lottoCount = Integer.parseInt(price) / 1000;
System.out.println("\n" + lottoCount + "개를 구매했습니다.");
List<Lotto> lottoNumList = Lotto.getLottoNum(lottoCount);
List<Set<Integer>> lottoNumSetList = Lotto.convertLottoToIntegerSet(lottoNumList);
System.out.println("\n당첨 번호를 입력해 주세요.");
String winningNumbers = Console.readLine();
Lotto.winningNumFormatValidator(winningNumbers);
Set<Integer> winningNumSet = Lotto.convertStringToIntegerSet(winningNumbers);
Lotto.winningNumValidator(winningNumSet);
System.out.println("\n보너스 번호를 입력해 주세요.");
String bonusNumber = Console.readLine();
Lotto.bonusNumValidator(bonusNumber, winningNumSet);
List<Integer> matchingCount = Lotto.getMatchingCount(lottoNumSetList, winningNumSet, Integer.parseInt(bonusNumber));
System.out.println("\n당첨 통계\n---");
Map<Integer, Integer> matchingCountNumber = Lotto.getMatchingCountNumber(matchingCount);
StringBuilder resultMessage = Lotto.convertMatchingInfoToMessage(matchingCountNumber);
System.out.println(resultMessage);
String benefit = Lotto.getBenefit(matchingCountNumber, price);
System.out.println("총 수익률은 " + benefit + "%입니다.");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
- 제한 사항, 요구 사항이 많아서 놓친 부분들도 많고, 코드도 효율적으로 리팩토링할 여지가 많은 것 같습니다.
리팩토링 하는 능력을 키우고, 이게 숙달되면 처음부터 좀 더 효율적인 클린코드를 구현할 수 있도록 계속 노력해야겠습니다.
[ 전체 메소드 ]
package UTEKO.ThirdWeek.lotto;
import camp.nextstep.edu.missionutils.Randoms;
import java.text.DecimalFormat;
import java.util.*;
public class Lotto {
private final List<Integer> numbers;
public Lotto(List<Integer> numbers) {
validate(numbers);
this.numbers = numbers;
}
private void validate(List<Integer> numbers) {
if (numbers.size() != 6) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 총 6개를 입력해야 합니다.");
}
if (numbers.size() == 6 && convertListToSet(numbers).size() != 6) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 중복될 수 없습니다.");
}
for (Integer eachNum:numbers
) {
if (eachNum < 1 || 45 < eachNum) {
throw new IllegalArgumentException("[ERROR] 로또 번호는 1부터 45 사이의 숫자여야 합니다.");
}
}
}
// TODO: 추가 기능 구현
@Override
public String toString() {
return "" + numbers ;
}
public static List<Lotto> getLottoNum(Integer lottoCount){
List<Lotto> lottoNumList = new ArrayList<>();
for (int i = 0; i < lottoCount; i++) {
Lotto lotto = new Lotto(Randoms.pickUniqueNumbersInRange(1, 45, 6));
Set sortedLotto = lotto.sortLottoNum(lotto);
lottoNumList.add(lotto);
System.out.println(sortedLotto);
}
return lottoNumList;
}
public Set sortLottoNum(Lotto lotto) {
Set sortingSet = new TreeSet();
for (Integer eachNum:lotto.numbers
) {
sortingSet.add(eachNum);
}
return sortingSet;
}
public static Set<Integer> convertStringToIntegerSet(String winningNumbers){
String[] split = winningNumbers.split(",");
Set<Integer> IntegerSet = new HashSet<>();
for (int i = 0; i < split.length; i++) {
IntegerSet.add(Integer.parseInt(split[i]));
}
return IntegerSet;
}
public static List<Set<Integer>> convertLottoToIntegerSet(List<Lotto> lottoList) {
List<Set<Integer>> LottoNumSetList = new ArrayList<>();
for (int i = 0; i < lottoList.size(); i++) {
Set<Integer> LottoNumSet = new HashSet<>();
List<Integer> lottoNums = lottoList.get(i).numbers;
for (Integer lottoNum:lottoNums
) {
LottoNumSet.add(lottoNum);
}
LottoNumSetList.add(LottoNumSet);
}
return LottoNumSetList;
}
public static List<Integer> convertSetToList(Set<Integer> lottoList) {
List<Integer> tempList = new ArrayList<>();
for (Integer lottoNum:lottoList
) {
tempList.add(lottoNum);
}
return tempList;
}
public static Set<Integer> convertListToSet(List<Integer> lottoList) {
Set<Integer> tempSet = new HashSet<>();
for (Integer lottoNum:lottoList
) {
tempSet.add(lottoNum);
}
return tempSet;
}
public static List<Integer> getMatchingCount(List<Set<Integer>> lottoList, Set<Integer> winningNumbers, int bonusNum) {
List<Integer> matchingCountList = new ArrayList<>();
for (int i = 0; i < lottoList.size(); i++) {
List<Integer> tempList = convertSetToList(lottoList.get(i));
Set<Integer> LottoNumSet = lottoList.get(i);
LottoNumSet.retainAll(winningNumbers);
if (LottoNumSet.size() == 5 && tempList.contains(bonusNum)) {
matchingCountList.add(7);
continue;
}
matchingCountList.add(LottoNumSet.size());
}
return matchingCountList;
}
public static Map<Integer,Integer> getMatchingCountNumber(List<Integer> matchingCountList) {
Map<Integer, Integer> matchingCount_Number = new HashMap<>();
for (int i = 0; i < 4; i++) {
matchingCount_Number.put(i + 3, 0);
}
matchingCount_Number.put(7, 0);
for (int j = 0; j < matchingCountList.size(); j++) {
for (Integer keySet:matchingCount_Number.keySet()) {
if (matchingCountList.get(j)>=3 && matchingCountList.get(j) == keySet) {
matchingCount_Number.put(keySet, matchingCount_Number.get(keySet) + 1);
}
}
}
return matchingCount_Number;
}
public enum matching {
THREE(3, 5000),
FOUR(4, 50000),
FIVE(5, 1500000),
SIX(6, 2000000000),
BONUS(7, 3000000);
private final int count, value;
private matching(int count, int value) {
this.count = count;
this.value = value;
}
public int getCount() {
return this.count;
}
public int getValue() {
return this.value;
}
}
public static String getBenefit(Map<Integer, Integer> matchingCountNum, String price) {
double totalPrice = 0;
for (Integer matchingCount:matchingCountNum.keySet()
) {
if (matchingCountNum.get(matchingCount) != 0) {
if (matching.THREE.getCount() == matchingCount) {totalPrice += matching.THREE.getValue() * matchingCountNum.get(matchingCount);}
if (matching.FOUR.getCount() == matchingCount) {totalPrice += matching.FOUR.getValue() * matchingCountNum.get(matchingCount);}
if (matching.FIVE.getCount() == matchingCount) {totalPrice += matching.FIVE.getValue() * matchingCountNum.get(matchingCount);}
if (matching.SIX.getCount() == matchingCount) {totalPrice += matching.SIX.getValue() * matchingCountNum.get(matchingCount);}
if (matching.BONUS.getCount() == matchingCount) {totalPrice += matching.BONUS.getValue() * matchingCountNum.get(matchingCount);}
}
}
return new DecimalFormat("###,##0.0").format((totalPrice/Integer.parseInt(price))*100);
}
public static StringBuilder convertMatchingInfoToMessage(Map<Integer, Integer> matchingCountNumber) {
StringBuilder sb = new StringBuilder();
sb.append("3개 일치 (5,000원) - ");
sb.append(matchingCountNumber.get(3) + "개\n");
sb.append("4개 일치 (50,000원) - ");
sb.append(matchingCountNumber.get(4) + "개\n");
sb.append("5개 일치 (1,500,000원) - ");
sb.append(matchingCountNumber.get(5) + "개\n");
sb.append("5개 일치, 보너스 볼 일치 (30,000,000원) - ");
sb.append(matchingCountNumber.get(7) + "개\n");
sb.append("6개 일치 (2,000,000,000원) - ");
sb.append(matchingCountNumber.get(6) + "개");
return sb;
}
public static void priceValidator(String price) {
if (!price.matches("[\\d]{1,8}")) {
throw new IllegalArgumentException("[ERROR] 1억 이하의 숫자만 입력 가능합니다. (1000원 단위)");
}
if (Integer.parseInt(price) % 1000 != 0 || price.equals("0")) {
throw new IllegalArgumentException("[ERROR] 구입은 1000원 단위로만 가능합니다.");
}
}
public static void winningNumFormatValidator(String winningNum) {
if (!winningNum.matches("[0-9]{1,2},[0-9]{1,2},[0-9]{1,2},[0-9]{1,2},[0-9]{1,2},[0-9]{1,2}")) {
throw new IllegalArgumentException("[ERROR] 당첨번호는 숫자,숫자,숫자... 형식으로 6개를 입력해주세요. ex)1,2,3,4,5,6");
}
}
public static void winningNumValidator(Set<Integer> winningNumSet) {
if (winningNumSet.size() != 6) {
throw new IllegalArgumentException("[ERROR] 당첨번호는 중복될 수 없습니다.");
}
for (Integer winnigNum:winningNumSet
) {
if (winnigNum < 0 || 45 < winnigNum) {
throw new IllegalArgumentException("[ERROR] 당첨번호는 1 ~ 45 사이의 숫자여야 합니다.");
}
}
}
public static void bonusNumValidator(String bonusNum, Set<Integer> winningNumSet) {
if (!bonusNum.matches("[0-9]{1,2}")) {
throw new IllegalArgumentException("[ERROR] 한 개의 숫자만 입력해 주세요.(1-45)");
}
if (Integer.parseInt(bonusNum) < 0 || 45 < Integer.parseInt(bonusNum)) {
throw new IllegalArgumentException("[ERROR] 1~45 사이의 숫자만 가능합니다.");
}
if (winningNumSet.contains(Integer.parseInt(bonusNum))) {
throw new IllegalArgumentException("[ERROR] 보너스 번호는 당첨번호와 중복될 수 없습니다.");
}
}
}
'Coding Test' 카테고리의 다른 글
2022 우테코 4th Week java-bridge 리뷰 (2) | 2022.11.18 |
---|---|
2022 우테코 onboarding 7번 리뷰 (0) | 2022.11.09 |
2022 우테코 onboarding 5~6번 리뷰 (0) | 2022.11.09 |
2022 우테코 onboarding 3~4번 리뷰 (0) | 2022.11.08 |
2022 우테코 onboarding 1~2번 리뷰 (0) | 2022.11.08 |