-
Notifications
You must be signed in to change notification settings - Fork 5
[로또] 송채원 미션 제출합니다. #2
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
Open
chaerishme
wants to merge
20
commits into
swthewhite-lab:main
Choose a base branch
from
chaerishme:chaerishme
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
70da198
feat: 로또 발행 기능 추가
0f917e9
feat: 사용자 입력 처리
96ff650
feat: 사용자 입력 유효성 검사 및 로또 생성 기능 추가
b62a7c7
feat: 당첨 개수와 보너스 여부로 등수 계산 기능 추가
d9ff960
feat: 수익률 계산 및 출력 기능 추가
b6577c2
Merge branch 'swthewhite-lab:main' into chaerishme
chaerishme 48fa131
fix: 당첨 출력 기능 업데이트
chaerishme 23c003a
feat: pytest 통과하도록 raise 추가
chaerishme 919927e
style: PEP8 black formatter 적용
chaerishme 5731f91
style: 독스트링 추가
chaerishme 1cda449
style: PEP8 형식 수정
chaerishme ca23f8d
Merge branch 'main' into chaerishme
swthewhite 1ad5f22
style: 불필요한 라인 제거
chaerishme 75d62cb
style: flake8 오류 해결
chaerishme a190769
style: flake8 오류 해결
chaerishme d228c44
Merge branch 'swthewhite-lab:main' into chaerishme
chaerishme 259a9af
style: 불필요한 라인 제거
chaerishme 1178a11
style: 불필요한 import문 제거
chaerishme 9234311
style: 쉼표 뒤 공백 추가
chaerishme 507a96e
feat: import문 최종 수정
chaerishme File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #### 컴퓨터 | ||
| * [x] 로또 구입 금액만큼 로또 발행 | ||
| * [x] 발행한 로또 오름차순으로 정렬하여 출력 | ||
| * [x] 로또 구입 금액 유효성 검사 | ||
| * [x] 로또 번호와 당첨 번호 비교 | ||
| * [x] 수익률 계산 (둘째자리 반올림) | ||
| * [x] 당첨 내역 및 수익률 출력 | ||
| * [x] 예외 상황 시 에러 문구 출력 후 다시 입력 받음 | ||
|
|
||
| #### 사용자 | ||
| * [x] 당첨 번호 입력 | ||
| * [x] 보너스 번호 입력 | ||
| * [x] 사용자 입력 유효성 검사 | ||
|
|
||
| #### 조건 | ||
| * [x] 함수나 메서드 길이 15라인 초과 금지 | ||
| * [x] else 예약어 사용 금지 | ||
| * [x] Enum 적용 | ||
| * [x] 로직 분리 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,77 @@ | ||
| from typing import List | ||
| from enum import Enum | ||
| import random | ||
|
|
||
|
|
||
| class Lotto: | ||
| def __init__(self, numbers: List[int]): | ||
| """ | ||
| 로또 번호 생성 및 유효성 검증하는 클래스 | ||
| """ | ||
|
|
||
| def __init__(self, numbers: list[int]): | ||
| """ | ||
| 로또 객체 초기화 | ||
| """ | ||
| self._validate(numbers) | ||
| self._numbers = numbers | ||
| self._numbers = sorted(numbers) | ||
|
|
||
| def _validate(self, numbers: List[int]): | ||
| def _validate(self, numbers: list[int]): | ||
| """ | ||
| 로또 번호 유효성 검사 | ||
| (로또 번호 6개, 중복 불가, 1~45의 범위) | ||
| """ | ||
| if len(numbers) != 6: | ||
| raise ValueError | ||
| raise ValueError("로또 번호는 6개여야 합니다.") | ||
| if len(set(numbers)) < 6: | ||
| raise ValueError("로또 번호는 중복되어서는 안됩니다.") | ||
| if max(numbers) > 45 or min(numbers) < 1: | ||
| raise ValueError("로또 번호의 숫자 범위는 1~45까지입니다.") | ||
|
|
||
| @classmethod | ||
| def generate_num(cls): | ||
| """ | ||
| 1~45 사이의 랜덤한 6개의 숫자로 로또 객체 생성 | ||
| """ | ||
| return cls(random.sample(range(1, 46), 6)) | ||
|
|
||
| def get_numbers(self): | ||
| """ | ||
| 로또 번호 리스트 반환 | ||
| """ | ||
| return self._numbers | ||
|
|
||
| def __str__(self): | ||
| """ | ||
| 로또 번호 문자열로 반환 | ||
| """ | ||
| return str(self._numbers) | ||
|
|
||
|
|
||
| class Rank(Enum): | ||
| """ | ||
| 로또 당첨 순위 정의하는 클래스 | ||
| """ | ||
|
|
||
| FIFTH = (3, False, 5_000) | ||
| FOURTH = (4, False, 50_000) | ||
| THIRD = (5, False, 1_500_000) | ||
| SECOND = (5, True, 30_000_000) | ||
| FIRST = (6, False, 2_000_000_000) | ||
| NONE = (0, False, 0) | ||
|
|
||
| def __init__(self, match_cnt, bonus_match, prize): | ||
| """ | ||
| Rank 객체 초기화 | ||
| """ | ||
| self.match_cnt = match_cnt | ||
| self.bonus_match = bonus_match | ||
| self.prize = prize | ||
|
|
||
| # TODO: 추가 기능 구현 | ||
| @classmethod | ||
| def get_rank(cls, match_cnt, bonus): | ||
| """ | ||
| 일치 개수와 보너스 번호 여부를 기반으로 당첨 순위 반환 | ||
| """ | ||
| for rank in cls: | ||
| if rank.match_cnt == match_cnt and rank.bonus_match == bonus: | ||
| return rank | ||
| return cls.NONE | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,144 @@ | ||
| from lotto import Rank | ||
| from lotto import Lotto | ||
| """ | ||
| 로또 프로그램 모듈. | ||
| 이 모듈은 로또 번호 생성, 당첨 확인, 결과 출력 등의 기능을 포함한다. | ||
| """ | ||
|
|
||
|
|
||
| def main(): | ||
| # TODO: 프로그램 구현 | ||
| pass | ||
| """ | ||
| 로또 프로그램 메인 함수 | ||
|
|
||
| 1. 사용자에게 금액 입력받고 해당 개수만큼 로또 번호 생성 | ||
| 2. 사용자에게서 당첨 번호와 보너스 번호 입력 받음 | ||
| 3. 로또 번호와 사용자가 선택한 번호 비교하여 결과 출력 | ||
| """ | ||
| count = input_price() | ||
| lotto_list = [Lotto.generate_num() for _ in range(count)] | ||
| print_lotto(lotto_list) | ||
|
|
||
| user_num = user_input() | ||
| bonus_num = bonus_input(user_num) | ||
|
|
||
| result, total_prize = compare_lotto(lotto_list, user_num, bonus_num) | ||
| print_result(result, total_prize, count) | ||
|
|
||
|
|
||
| def input_price(): | ||
| """ | ||
| 사용자에게서 로또 구입 금액 입력받아 유효성 검사하는 함수 | ||
| """ | ||
| while True: | ||
| try: | ||
| print("구입금액을 입력해 주세요.") | ||
| price = input() | ||
| return validate_price(price) | ||
| except ValueError as e: | ||
| print(f"[ERROR] {e}") | ||
| raise | ||
|
|
||
|
|
||
| def validate_price(price): | ||
| """ | ||
| 입력된 금액 유효성 검증 후 로또 개수 반환 | ||
| """ | ||
| if not price.isdigit(): | ||
| raise ValueError("[ERROR] 숫자를 입력해 주세요.\n") | ||
| if int(price) % 1000 != 0: | ||
| raise ValueError("구입 금액은 1,000원으로 나누어 떨어져야 합니다.\n") | ||
| if int(price) < 1000: | ||
| raise ValueError("구입 금액은 1,000원 이상이어야 합니다.\n") | ||
|
|
||
| return int(price) // 1000 | ||
|
|
||
|
|
||
| def print_lotto(lotto_list): | ||
| """ | ||
| 생성된 로또 번호 출력 | ||
| """ | ||
| print(f"\n{len(lotto_list)}개를 구매했습니다.") | ||
| for lotto in lotto_list: | ||
| print(lotto) | ||
|
|
||
|
|
||
| def user_input(): | ||
| """ | ||
| 사용자로부터 당첨 번호 입력받아 반환 | ||
| """ | ||
| while True: | ||
| print("\n당첨 번호를 입력해 주세요.") | ||
| try: | ||
| user_num = list(map(int, input().split(","))) | ||
| return Lotto(user_num).get_numbers() | ||
| except ValueError as e: | ||
| print(f"[ERROR] {e}") | ||
|
|
||
|
|
||
| def bonus_input(user_num): | ||
| """ | ||
| 사용자로부터 보너스 번호 입력받아 반환 | ||
| """ | ||
| while True: | ||
| try: | ||
| bonus_num = input("\n보너스 번호를 입력해 주세요.\n") | ||
| return validate_bonus(bonus_num, user_num) | ||
| except ValueError as e: | ||
| print(f"[ERROR] {e}") | ||
|
|
||
|
|
||
| def validate_bonus(bonus_num, user_num): | ||
| """ | ||
| 입력된 보너스 번호 유효성 검사 후 반환 | ||
| """ | ||
| if not bonus_num.isdigit(): | ||
| raise ValueError("숫자를 입력해 주세요.") | ||
| if int(bonus_num) in user_num: | ||
| raise ValueError("보너스 숫자와 입력한 당첨 번호는 중복되지 않아야 합니다.") | ||
| if int(bonus_num) > 45 or int(bonus_num) < 1: | ||
| raise ValueError("로또 번호의 숫자 범위는 1~45까지입니다.") | ||
|
|
||
| return int(bonus_num) | ||
|
|
||
|
|
||
| def compare_lotto(lotto_list, user_num, bonus_num): | ||
| """ | ||
| 로또 번호와 사용자가 선택한 번호 비교하여 당첨 결과 계산 | ||
| """ | ||
| result = {rank: 0 for rank in Rank} | ||
| total_prize = 0 | ||
|
|
||
| for lotto in lotto_list: | ||
| lotto_num = lotto.get_numbers() | ||
| match_cnt = len(set(user_num) & set(lotto_num)) | ||
| bonus = bonus_num in lotto_num | ||
|
|
||
| rank = Rank.get_rank(match_cnt, bonus) | ||
| result[rank] += 1 | ||
| total_prize += rank.prize | ||
|
|
||
| return result, total_prize | ||
|
|
||
|
|
||
| def print_result(result, total_prize, count): | ||
| """ | ||
| 당첨 결과 출력 | ||
| """ | ||
| profit_rate = round((total_prize / (count * 1000)) * 100, 2) | ||
|
|
||
| print("\n당첨 통계") | ||
| print("---") | ||
| for rank in Rank: | ||
| if rank == Rank.SECOND: | ||
| print(f"{rank.match_cnt}개 일치, 보너스 볼 일치 ({rank.prize:,}원) - " | ||
| f"{result[rank]}개") | ||
|
|
||
| if rank != Rank.NONE and rank != Rank.SECOND: | ||
| print(f"{rank.match_cnt}개 일치 ({rank.prize:,}원) - " | ||
| f"{result[rank]}개") | ||
|
|
||
| print(f"총 수익률은 {profit_rate}%입니다.") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
🛠️ Refactor suggestion
에러 처리 로직을 개선해주세요.
에러를 출력하고 다시 발생시키는 것은 중복된 처리입니다. 다음과 같이 수정하는 것이 좋겠습니다:
try: print("구입금액을 입력해 주세요.") price = input() return validate_price(price) except ValueError as e: print(f"[ERROR] {e}") - raise📝 Committable suggestion