-
Notifications
You must be signed in to change notification settings - Fork 1.1k
3단계 - 로또(2등) #4214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
3단계 - 로또(2등) #4214
Changes from 12 commits
1f93118
451d4f9
8cafa4c
e3bef8b
0403d84
a5caacf
e1bfb3b
cd5f4b8
030f472
4be4d31
57ce83b
f75bfde
ac909b4
d148e86
17845eb
73ec000
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,19 @@ | ||
| package lotto; | ||
|
|
||
| import lotto.model.PurchaseAmount; | ||
| import lotto.model.Lotto; | ||
| import lotto.model.LottoResults; | ||
| import lotto.model.Lottos; | ||
| import lotto.model.*; | ||
| import lotto.view.InputView; | ||
| import lotto.view.OutputView; | ||
|
|
||
| public class LottoApplication { | ||
| public static void main(String[] args) { | ||
| PurchaseAmount purchaseAmount = InputView.readBudgetInput(); | ||
| Lotto winningLotto = InputView.readWinningLottoInput(); | ||
| WinningLotto winningLotto = InputView.readWinningLottoInput(); | ||
|
|
||
| OutputView.printPurchaseCount(purchaseAmount.countLottoTickets()); | ||
| Lottos lottos = purchaseAmount.buyLottos(); | ||
| OutputView.printBoughtLottos(lottos); | ||
|
|
||
| LottoResults result = lottos.calculateResults(winningLotto); | ||
| LottoResults result = LottoResultCalculator.calculate(lottos, winningLotto); | ||
| OutputView.printResults(result, purchaseAmount); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,68 +1,54 @@ | ||
| package lotto.model; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.*; | ||
| import java.util.stream.Collectors; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| public class Lotto { | ||
| private final List<LottoNumber> numbers; | ||
| private final static int LOTTO_NUMBER_SIZE = 6; | ||
| private final static List<Integer> rangedInts = IntStream.rangeClosed(1, 45).boxed().collect(Collectors.toList()); | ||
| private final Set<LottoNumber> numbers; | ||
|
|
||
| public Lotto() { | ||
| this(generateRandomNumbers()); | ||
| } | ||
|
|
||
| public Lotto(int... numbers) { | ||
| this(Arrays.stream(numbers).boxed().collect(Collectors.toList())); | ||
| this(Arrays.stream(numbers).mapToObj(LottoNumberFactory::get).collect(Collectors.toSet())); | ||
| } | ||
|
|
||
| public Lotto(List<Integer> numbers) { | ||
| public Lotto(Set<LottoNumber> numbers) { | ||
| checkValidity(numbers); | ||
| Collections.sort(numbers); | ||
| this.numbers = numbers.stream().map(LottoNumber::new).collect(Collectors.toList()); | ||
| } | ||
|
|
||
| public List<LottoNumber> value() { | ||
| return Collections.unmodifiableList(this.numbers); | ||
| this.numbers = numbers; | ||
| } | ||
|
|
||
| public int countMatchNumbers(Lotto lotto) { | ||
| int matchCount = 0; | ||
| for (LottoNumber number : this.numbers) { | ||
| matchCount += addMatchCount(number, lotto); | ||
| } | ||
| return matchCount; | ||
| return Math.toIntExact(this.numbers.stream().filter(lotto::contains).count()); | ||
| } | ||
|
|
||
| private void checkValidity(List<Integer> numbers) { | ||
| if (numbers.size() != 6) { | ||
| throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); | ||
| } | ||
| if (hasDuplicated(numbers)) { | ||
| throw new IllegalArgumentException("로또 번호는 중복될 수 없습니다."); | ||
| } | ||
| public boolean matchesBonusNumber(LottoNumber bonusNumber) { | ||
| return contains(bonusNumber); | ||
| } | ||
|
|
||
| private boolean hasDuplicated(List<Integer> numbers) { | ||
| long distinctCount = numbers.stream().distinct().count(); | ||
| return distinctCount != numbers.size(); | ||
| @Override | ||
| public String toString() { | ||
| List<LottoNumber> lottoNumbers = new ArrayList<>(this.numbers); | ||
| Collections.sort(lottoNumbers); | ||
| return lottoNumbers.toString(); | ||
| } | ||
|
|
||
| private int addMatchCount(LottoNumber number, Lotto lotto) { | ||
| if (lotto.contains(number)) { | ||
| return 1; | ||
| } | ||
| return 0; | ||
| public boolean contains(LottoNumber number) { | ||
| return numbers.contains(number); | ||
| } | ||
|
|
||
| private boolean contains(LottoNumber number) { | ||
| return numbers.contains(number); | ||
| private void checkValidity(Set<LottoNumber> numbers) { | ||
| if (numbers.size() != LOTTO_NUMBER_SIZE) { | ||
| throw new IllegalArgumentException("로또 번호는 6개여야 합니다."); | ||
| } | ||
| } | ||
|
|
||
| private static List<Integer> generateRandomNumbers() { | ||
| List<Integer> array = IntStream.rangeClosed(1, 45).boxed().collect(Collectors.toList()); | ||
| Collections.shuffle(array); | ||
| return array.subList(0, 6); | ||
| private static Set<LottoNumber> generateRandomNumbers() { | ||
| Collections.shuffle(rangedInts); | ||
| return rangedInts.subList(0, LOTTO_NUMBER_SIZE).stream().map(LottoNumberFactory::get).collect(Collectors.toSet()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |||||
|
|
||||||
| import java.util.Objects; | ||||||
|
|
||||||
| public class LottoNumber { | ||||||
| public class LottoNumber implements Comparable<LottoNumber> { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 상황
위 요구사항을 서버에서 생성되는 LottoNumber의 인스턴스의 갯수는? 동시에 생성되는 인스턴스 갯수가 너무 많다. 힌트 : Map과 같은 곳에 인스턴스를 생성한 후 재사용하는 방법을 찾아본다. |
||||||
| private final int number; | ||||||
|
|
||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
문자열을 받는 생성자를 추가할 경우 의미있을까? |
||||||
| public LottoNumber(int number) { | ||||||
|
||||||
|
|
@@ -36,4 +36,9 @@ public int hashCode() { | |||||
| public String toString() { | ||||||
| return String.valueOf(number); | ||||||
| } | ||||||
|
|
||||||
| @Override | ||||||
| public int compareTo(LottoNumber another) { | ||||||
| return Integer.compare(this.number, another.number); | ||||||
| } | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package lotto.model; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| public class LottoNumberFactory { | ||
|
||
| private final static Map<Integer, LottoNumber> CACHE; | ||
|
|
||
| static { | ||
| CACHE = new ConcurrentHashMap<>(); | ||
| IntStream.rangeClosed(1, 45).forEach(i -> CACHE.put(i, new LottoNumber(i))); | ||
| } | ||
|
|
||
| public static LottoNumber get(String number) { | ||
| return get(Integer.parseInt(number)); | ||
| } | ||
|
|
||
| public static LottoNumber get(Integer number) { | ||
| if (CACHE.get(number) == null) { | ||
| throw new IllegalArgumentException("로또 번호는 1부터 45 사이의 숫자여야 합니다."); | ||
| } | ||
| return CACHE.get(number); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,11 @@ | ||||||||||||||
| package lotto.model; | ||||||||||||||
|
|
||||||||||||||
| public class LottoResultCalculator { | ||||||||||||||
| public static LottoResults calculate(Lottos lottos, WinningLotto winningLotto) { | ||||||||||||||
| LottoResults lottoResults = new LottoResults(); | ||||||||||||||
| for (Lotto lotto : lottos.lottos()) { | ||||||||||||||
| lottoResults.update(winningLotto.calculatePrize(lotto)); | ||||||||||||||
| } | ||||||||||||||
| return lottoResults; | ||||||||||||||
|
||||||||||||||
| LottoResults lottoResults = new LottoResults(); | |
| for (Lotto lotto : lottos.lottos()) { | |
| lottoResults.update(winningLotto.calculatePrize(lotto)); | |
| } | |
| return lottoResults; | |
| LottoResults lottoResults = lottos.match(winningLotto); |
이와 같이 Lottos에 메시지를 보내 위와 같이 구현해도 되지 않을까?
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,59 +1,48 @@ | ||||||
| package lotto.model; | ||||||
|
|
||||||
| import java.util.Arrays; | ||||||
| import java.util.HashMap; | ||||||
| import java.util.Map; | ||||||
| import java.util.Objects; | ||||||
|
|
||||||
| public class LottoResults { | ||||||
| private final Map<Integer, Integer> matchCounts; | ||||||
| private final Map<Prize, Integer> prizeCounts; | ||||||
|
|
||||||
| public LottoResults() { | ||||||
| this(new HashMap<>()); | ||||||
| } | ||||||
|
|
||||||
| public LottoResults(Map<Integer, Integer> matchCounts) { | ||||||
| this.matchCounts = matchCounts; | ||||||
| public LottoResults(Map<Prize, Integer> prizeCounts) { | ||||||
| this.prizeCounts = prizeCounts; | ||||||
| } | ||||||
|
|
||||||
| public void updateMatchCount(int matchCount) { | ||||||
| if (matchCount < 3) { | ||||||
| return; | ||||||
| } | ||||||
| matchCounts.put(matchCount, matchCounts.getOrDefault(matchCount, 0) + 1); | ||||||
| public void update(Prize prize) { | ||||||
| prizeCounts.put(prize, prizeCounts.getOrDefault(prize, 0) + 1); | ||||||
| } | ||||||
|
|
||||||
| public long getPrizeValue() { | ||||||
| return matchCounts.entrySet().stream() | ||||||
| .mapToLong(entry -> (long) entry.getValue() * Prize.fromMatchCount(entry.getKey()).value()) | ||||||
| public long getTotalPrizeValue() { | ||||||
|
||||||
| public long getTotalPrizeValue() { | |
| public Money getTotalPrizeValue() { |
이와 같이 구현할 경우 수익률은 누가 계산하는 것이 맞을까?
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,46 +1,37 @@ | ||
| package lotto.model; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| public class Lottos { | ||
| private final List<Lotto> lottos; | ||
|
|
||
| public Lottos(int count) { | ||
| this(new ArrayList<>()); | ||
| for (int i = 0; i < count; i++) { | ||
| lottos.add(new Lotto()); | ||
| } | ||
| this(createLottos(count)); | ||
| } | ||
|
|
||
| public Lottos(List<Lotto> lottos) { | ||
| this.lottos = lottos; | ||
| } | ||
|
|
||
| public LottoResults calculateResults(Lotto winningLotto) { | ||
| LottoResults results = new LottoResults(); | ||
|
|
||
| for (Lotto lotto : lottos) { | ||
| int matchCount = lotto.countMatchNumbers(winningLotto); | ||
| results.updateMatchCount(matchCount); | ||
| } | ||
|
|
||
| return results; | ||
| } | ||
|
|
||
| private void addMatchCount(int matchCount, List<Integer> results) { | ||
| if (matchCount >= 3 && matchCount <= 6) { | ||
| int idx = matchCount - 3; | ||
| results.set(idx, results.get(idx) + 1); | ||
| } | ||
| public List<Lotto> lottos() { | ||
| return Collections.unmodifiableList(lottos); | ||
| } | ||
|
|
||
| public String toString() { | ||
| StringBuilder sb = new StringBuilder(); | ||
| for (Lotto lotto : lottos) { | ||
| sb.append(lotto.value().toString()).append("\n"); | ||
| sb.append(lotto.toString()).append("\n"); | ||
| } | ||
| return sb.toString(); | ||
| } | ||
|
|
||
| private static List<Lotto> createLottos(int count) { | ||
| List<Lotto> lottos = new ArrayList<>(); | ||
| for (int i = 0; i < count; i++) { | ||
| lottos.add(new Lotto()); | ||
| } | ||
| return lottos; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package lotto.model; | ||
|
|
||
| public class WinningLotto { | ||
| private final Lotto winningLotto; | ||
| private final LottoNumber bonusNumber; | ||
|
|
||
| public WinningLotto(Lotto lotto, LottoNumber bonusNumber) { | ||
| if (lotto.contains(bonusNumber)) { | ||
| throw new IllegalArgumentException("당첨 번호는 보너스볼의 번호를 포함할 수 없습니다."); | ||
| } | ||
| this.winningLotto = lotto; | ||
| this.bonusNumber = bonusNumber; | ||
| } | ||
|
|
||
| public Prize calculatePrize(Lotto lotto) { | ||
| int matchCount = lotto.countMatchNumbers(winningLotto); | ||
| boolean matchBonus = lotto.matchesBonusNumber(bonusNumber); | ||
| return Prize.valueOf(matchCount, matchBonus); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍