Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
- 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발급한다.
- 로또 1장의 가격은 1,000원이다.
- 로또 번호는 1~45 사이의 숫자 6개로 구성된다.
- 수동으로 구매할 로또 수를 입력받는다.
- 수동으로 구매할 로또 번호를 입력받는다.
- 당첨 번호 6개를 입력받는다.
- 보너스 번호 1개를 입력받는다.
- 발행한 로또와 당첨 번호를 비교하여 당첨 통계를 계산한다.
Expand All @@ -51,14 +53,16 @@

### 로또 기계

- 구입 금액을 기준으로 발행할 로또 장수를 계산한다.
- 자동 발행 로또 수를 계산한다.
- 각 로또와 당첨 번호를 비교하여 당첨 통계를 계산한다.
- 당첨 금액 및 수익률을 계산한다.

### 입력

- 구입 금액을 입력받는다.
- 1,000원 단위의 양수
- 수동으로 구매할 로또 수를 입력받는다.
- 수동으로 구매할 번호를 입력받는다.
- 당첨 번호 6개와 보너스 번호 1개를 입력받는다.
- 1~45 사이의 숫자, 중복 불가

Expand Down
23 changes: 23 additions & 0 deletions src/main/java/lotto/AutoLottosGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package lotto;

import java.util.ArrayList;
import java.util.List;

public class AutoLottosGenerator implements LottosGenerator {

private final int count;

public AutoLottosGenerator(int count) {
this.count = count;
}

@Override
public Lottos generate() {
List<Lotto> lottos = new ArrayList<>();
for (int i = 0; i < count; i++) {
lottos.add(LottoMachine.randomLotto());
}
return new Lottos(lottos);
}

}
19 changes: 19 additions & 0 deletions src/main/java/lotto/InputRetry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package lotto;

import java.util.function.Supplier;

public class InputRetry {

private InputRetry() {
}

public static <T> T retry(Supplier<T> action) {
while (true) {
try {
return action.get();
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
}
23 changes: 15 additions & 8 deletions src/main/java/lotto/Lotto.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class Lotto {
public static final int LOTTO_NUMBER_COUNT = 6;

private static final String ERROR_INVALID_COUNT = "로또 번호는 6개여야 한다";
private static final String ERROR_DUPLICATE_NUMBER = "로또 번호에 중복이 있을 수 없습니다.";
private static final String ERROR_INVALID_FORMAT = "숫자 형식이 올바르지 않습니다: ";

private final Set<LottoNumber> numbers;

Expand All @@ -34,6 +36,14 @@ public static Lotto fromIntegers(List<Integer> numbers) {
return new Lotto(toLottoNumbers(numbers));
}

public List<LottoNumber> numbers() {
return Collections.unmodifiableList(new ArrayList<>(numbers));
}

public boolean contains(LottoNumber number) {
return numbers.contains(number);
}

private static List<LottoNumber> toLottoNumbers(List<Integer> numbers) {
return numbers.stream()
.map(LottoNumber::of)
Expand All @@ -53,22 +63,19 @@ private static int parseIntOrThrow(String s) {
try {
return Integer.parseInt(s.trim());
} catch (NumberFormatException e) {
throw new IllegalArgumentException("숫자 형식이 올바르지 않습니다: " + s);
throw new IllegalArgumentException(ERROR_INVALID_FORMAT + s);
}
}

private static void validateNumbersCount(List<LottoNumber> numbers) {
if (numbers.size() != LOTTO_NUMBER_COUNT) {
throw new IllegalArgumentException(ERROR_INVALID_COUNT);
}
}

public List<LottoNumber> numbers() {
return Collections.unmodifiableList(new ArrayList<>(numbers));
}

public boolean contains(LottoNumber number) {
return numbers.contains(number);
long distinctCount = numbers.stream().distinct().count();
if (distinctCount != LOTTO_NUMBER_COUNT) {
throw new IllegalArgumentException(ERROR_DUPLICATE_NUMBER);
}
}

@Override
Expand Down
45 changes: 37 additions & 8 deletions src/main/java/lotto/LottoApplication.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,54 @@
package lotto;

import java.util.List;
import lotto.view.InputView;
import lotto.view.ResultView;

public class LottoApplication {

public static void main(String[] args) {

int input = InputView.readPurchaseAmount();
PurchaseAmount amount = new PurchaseAmount(input);
PurchaseAmount amount = createPurchaseAmount();

Lottos lottos = LottoMachine.randomLottos(amount.ticketCount());
ResultView.printPurchasedLottos(lottos);
ManualLottoCount manualCount = createManualLottoCount(amount);
Lottos manualLottos = createManualLottos(manualCount);
Lottos autoLottos = new AutoLottosGenerator(amount.autoCount(manualCount)).generate();

Lotto winningNumbers = new Lotto(InputView.readWinningNumbers());
LottoNumber bonusNumber = LottoNumber.of(InputView.readBonusNumber());
Lottos purchased = manualLottos.merge(autoLottos);
ResultView.printPurchasedLottos(purchased, manualCount);

LottoMatchResult matchResult = lottos.matchResult(
new WinningNumbers(winningNumbers, bonusNumber));
WinningNumbers winningNumbers = createWinningNumbers();
LottoMatchResult matchResult = purchased.matchResult(winningNumbers);
ProfitRate profitRate = new ProfitRate(matchResult.totalPrize(), amount);

ResultView.printLottoResult(matchResult, profitRate);
}

private static PurchaseAmount createPurchaseAmount() {
return InputRetry.retry(() ->
new PurchaseAmount(InputView.readPurchaseAmount())
);
}

private static ManualLottoCount createManualLottoCount(PurchaseAmount amount) {
return InputRetry.retry(() ->
new ManualLottoCount(InputView.readManualLottoCount(), amount)
);
}

private static Lottos createManualLottos(ManualLottoCount manualCount) {
return InputRetry.retry(() -> {
List<String> manualNumbers = InputView.readManualLottos(manualCount.count());
LottosGenerator generator = new ManualLottosGenerator(manualNumbers);
return generator.generate();
});
}

private static WinningNumbers createWinningNumbers() {
return InputRetry.retry(() -> {
Lotto winning = new Lotto(InputView.readWinningNumbers());
LottoNumber bonus = LottoNumber.of(InputView.readBonusNumber());
return new WinningNumbers(winning, bonus);
});
}
}
10 changes: 1 addition & 9 deletions src/main/java/lotto/LottoMachine.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,7 @@

public class LottoMachine {

public static Lottos randomLottos(int count) {
List<Lotto> lottos = new ArrayList<>();
for (int i = 0; i < count; i++) {
lottos.add(randomLotto());
}
return new Lottos(lottos);
}

private static Lotto randomLotto() {
public static Lotto randomLotto() {
List<Integer> numbers = new ArrayList<>();
for (int i = Lotto.MIN_NUMBER; i <= Lotto.MAX_NUMBER; i++) {
numbers.add(i);
Expand Down
12 changes: 5 additions & 7 deletions src/main/java/lotto/LottoNumber.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package lotto;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class LottoNumber implements Comparable<LottoNumber> {
Expand All @@ -9,11 +11,11 @@ public class LottoNumber implements Comparable<LottoNumber> {

private static final String ERROR_OUT_OF_RANGE = "로또 번호는 1~45 범위의 숫자여야 한다";

private static final LottoNumber[] CACHE = new LottoNumber[MAX_NUMBER + 1];
private static final Map<Integer, LottoNumber> CACHE = new HashMap<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


static {
for (int i = MIN_NUMBER; i <= MAX_NUMBER; i++) {
CACHE[i] = new LottoNumber(i);
CACHE.put(i, new LottoNumber(i));
}
}

Expand All @@ -26,11 +28,7 @@ private LottoNumber(int number) {

public static LottoNumber of(int number) {
validateRange(number);
return CACHE[number];
}

public static LottoNumber of(String number) {
return of(Integer.parseInt(number));
return CACHE.get(number);
}

public int number() {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/lotto/LottoRank.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,11 @@ public static LottoRank of(int matchCount, boolean hasBonus) {
.orElse(MISS);
}

public boolean isMiss() {
return this == MISS;
}

public boolean isSecond() {
return this == SECOND;
}
}
10 changes: 10 additions & 0 deletions src/main/java/lotto/Lottos.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ public Lottos(List<Lotto> lottos) {
this.lottos = lottos;
}

public static Lottos manualLottos(List<String> manualNumbers) {
return new Lottos(manualNumbers.stream().map(Lotto::new).toList());
}

public Lottos merge(Lottos other) {
List<Lotto> mergedLottos = new ArrayList<>(this.lottos);
mergedLottos.addAll(other.lottos);
return new Lottos(mergedLottos);
}

public int count() {
return lottos.size();
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/lotto/LottosGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package lotto;

public interface LottosGenerator {

Lottos generate();
}
35 changes: 35 additions & 0 deletions src/main/java/lotto/ManualLottoCount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package lotto;

public class ManualLottoCount {

private static final String ERROR_NEGATIVE_COUNT = "수동 로또 수량은 0 이상이어야 합니다.";
private static final String ERROR_EXCEED_PURCHASE = "수동 장수는 구입 가능한 수량을 초과할 수 없습니다.";
private final int count;

public ManualLottoCount(int count, int purchaseAmount) {
this(count, new PurchaseAmount(purchaseAmount));
}

public ManualLottoCount(int count, PurchaseAmount amount) {
validateNonNegativeCount(count);
validateNotExceedPurchaseAmount(count, amount);
this.count = count;
}

public int count() {
return count;
}

private static void validateNonNegativeCount(int count) {
if (count < 0) {
throw new IllegalArgumentException(ERROR_NEGATIVE_COUNT);
}
}

private static void validateNotExceedPurchaseAmount(int count, PurchaseAmount amount) {
if (amount.ticketCount() < count) {
throw new IllegalArgumentException(ERROR_EXCEED_PURCHASE);
}
}

}
17 changes: 17 additions & 0 deletions src/main/java/lotto/ManualLottosGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package lotto;

import java.util.List;

public class ManualLottosGenerator implements LottosGenerator {

private final List<String> manualNumbers;

public ManualLottosGenerator(List<String> manualNumbers) {
this.manualNumbers = manualNumbers;
}

@Override
public Lottos generate() {
return new Lottos(manualNumbers.stream().map(Lotto::new).toList());
}
}
5 changes: 4 additions & 1 deletion src/main/java/lotto/PurchaseAmount.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ public int ticketCount() {
return value / PRICE_PER_LOTTO;
}

public int autoCount(ManualLottoCount manualCount) {
return ticketCount() - manualCount.count();
}

private static void validate(int amount) {
if (amount < PRICE_PER_LOTTO || amount % PRICE_PER_LOTTO != 0) {
throw new IllegalArgumentException(ERROR_INVALID_PURCHASE_AMOUNT);
}
}

}
Loading