2025. 10. 1. 18:19ㆍTIL
오늘은 부트캠프 중 심화 과정 문제의 quest들을 해결해보았다.
1. 랜덤한 닉네임 만들기
- 기절초풍, 멋있는, 재미있는
- 도전적인, 노란색의, 바보같은
- 돌고래, 개발자, 오랑우탄
다음과 같은 키워드를 바탕으로, 27개의 랜덤한 닉네임을 설정할 수 있는 코드를 작성해 보자.
3 x 3 x 3 = 27이므로, 각각의 키워드 모음 중 하나씩을 선정해 붙여서 랜덤한 닉네임을 만들 수 있다.
해결 과정의 사고 메커니즘은 다음과 같았다.
1) 각각의 키워드 모음을 리스트화하자.
2) Randrange 함수를 통해 각 리스트 함수에서 아무 단어나 꺼내자.
3) 꺼낸 단어들을 붙이자.
import random
name_list1 = ['기절초풍', '멋있는', '재미있는']
name_list2 = ['도전적인', '노란색의', '바보같은']
name_list3 = ['돌고래', '개발자', '오랑우탄'] #키워드 모음 리스트화
def create_random_nickname():
num1 = random.randrange(0,3)
num2 = random.randrange(0,3)
num3 = random.randrange(0,3) #randrange 함수를 통한 리스트별 무작위 단어 추출
return name_list1[num1]+name_list2[num2]+name_list3[num3] #추출한 무작위 단어 조합
my_nickname = create_random_nickname()
print(my_nickname)
굳이 함수를 쓰지는 않아도 됐을 것 같지만, create_random_nickname이라는 함수를 만들어 리스트의 내용이 수정되었을 때도 코드의 큰 수정 없이 잘 동작할 수 있도록 만들었다.
2. 자판기 만들기
- 사이다 1700원
- 콜라 1900원
- 식혜 2500원
- 솔의눈 3000원
왜 솔의눈이 제일 비싼지는 그냥 넘어가기로 하자
자판기의 조건은 다음과 같다.
1. 사용자가 볼 수 있게 메뉴를 표시한다.
2. 사용자는 음료를 선택할 수 있다.
※ 목록에 없는 음료일 경우 실행이 종료된다.
3. 사용자는 지불할 금액을 입력한다.
※ 지불하는 금액이 선택한 음료의 비용보다 작다면 "돈이 부족합니다."를 출력한다.
4. 사용자는 음료를 구매하고 남은 잔액을 확인할 수 있다.
해결 과정의 메커니즘은 다음과 같았다.
1) 음료의 모음을 dictionary로 만들자. (key와 value가 짝으로 있으므로)
2) 음료의 이름을 받고, 음료 이름이 dictionary에 있는지 확인하는 조건문을 만들자.
3) 2)에서 만든 조건문 안에, 지불 금액을 입력받고, 돈이 부족할 때/충분할 때 각각의 조건에 따라 "돈이 부족합니다"를 출력하거나 잔액을 계산하도록 하자.
drinks = {'사이다':1700, '콜라':1900, '식혜':2500, '솔의눈':3000} #음료 모음 dictionary화
print(drinks) #음료 모음 출력
user_choice = input('음료:') #음료 이름 입력
if user_choice in drinks.keys(): #조건1 : 입력한 음료가 drinks의 key 값들 안에 있는지?
user_money = int(input('지불 금액:')) #지불 금액 입력
if user_money < drinks[user_choice]: #조건2 : 지불 금액이 입력한 음료의 value값보다 작은지?
print('돈이 부족합니다')
else:
print(f'잔액 : {user_money-drinks[user_choice]}원')
우선 dictionary를 작성하는 문법에 대해 다시 한 번 공부하게 되었다. 처음에는 list에 담아야 될 줄 알았는데, 굳이 그럴 필요가 없었다..
그리고 keys() 함수에 대해 배웠다. Dictionary 자료에 대해 keys()를 수행하면, 해당 dictionary의 모든 key 값들을 불러온다.
이 코드에서 drinks.keys()를 수행하면, 결과는 ['사이다', '콜라', '식혜', '솔의눈']의 list 형태로 출력될 것이다.
3. 단어 맞추기 게임 (Hangman) 만들기
문제의 조건은 다음과 같다.
1. 컴퓨터가 랜덤으로 영어단어를 선택한다. (단어는 list에 존재) 그리고 단어의 자리수를 힌트로 제공한다.
2. 사용자는 A부터 Z까지의 알파벳 중 하나를 선택하며,
※ 맞출 경우 해당 알파벳이 들어간 자리를 전부 보여준다.
※ 틀릴 경우 목숨이 하나 줄어든다.
3. 사용자가 9번 틀리면 게임이 종료된다.
4. 게임 종료 전 영어 단어의 모든 자리를 알아내면 플레이어의 승리이다.
해결 과정의 메커니즘은 다음과 같았다.
1) List에 있는 영어 단어를 무작위로 선택하고, 그 자릿수를 계산한다.
2) 기본값으로 '_'가 자리수만큼 있는 문자열을 만들고, 사용자가 입력한 알파벳이 정답 단어에 존재한다면, 알파벳의 위치와 위치에 맞게 알파벳을 표시한다.
3) 알파벳이 정답에 없다면 목숨을 1 깎는다.
4) 목숨이 0이 되면 실패, 모든 알파벳을 다 찾아서 '_'가 없어지면 플레이어의 승리.
import random as rd
words = ["airplane", "apple", "arm", "bakery", "banana", "bank", "bean", "belt", "bicycle", "biography", "blackboard", "boat", "bowl", "broccoli", "bus", "car", "carrot", "chair", "cherry", "cinema", "class", "classroom", "cloud", "coat", "cucumber", "desk", "dictionary", "dress", "ear", "eye", "fog", "foot", "fork", "fruits", "hail", "hand", "head", "helicopter", "hospital", "ice", "jacket", "kettle", "knife", "leg", "lettuce", "library", "magazine", "mango", "melon", "motorcycle", "mouth", "newspaper", "nose", "notebook", "novel", "onion", "orange", "peach", "pharmacy", "pineapple", "plate", "pot", "potato", "rain", "shirt", "shoe", "shop", "sink", "skateboard", "ski", "skirt", "sky", "snow", "sock", "spinach", "spoon", "stationary", "stomach", "strawberry", "student", "sun", "supermarket", "sweater", "teacher", "thunderstorm", "tomato", "trousers", "truck", "vegetables", "vehicles", "watermelon", "wind"]
answer = words[rd.randrange(0,92)] #랜덤 단어 추출
print('정답의 자리수 : {0}'.format(len(answer))) #정답 단어의 자리수
life = 9
masked = "_" * len(answer) #기본 문자열
while life > 0:
print(masked)
alphabet = input("알파벳을 입력하세요 : ")
if alphabet in answer: #조건1 : 알파벳이 정답 단어에 있는지?
masked = "".join([ch if ch == alphabet or masked[i] != "_" else "_" for i, ch in enumerate(answer)])
#List comprehension을 통한 matched 알파벳 입력
else:
life -= 1
print('남은 목숨 : {0}'.format(life))
if "_" not in masked: #조건2 : 정답 단어의 모든 알파벳을 찾은 경우
print("축하합니다. 정답은 {0}".format(answer))
break
if life == 0: #조건3 : 목숨 내에 정답 단어의 모든 알파벳을 찾지 못한 경우
print("실패! 정답은 {0}".format(answer))
퀘스트 중에서 가장 어려웠고 지금까지 봤던 Python 문제 중에서 가장 생각하기 어려웠다.
특히 알파벳이 정답 단어에 있는 경우 그 알파벳의 위치를 어떻게 표현할 것인지, 그리고 어떻게 정답 알파벳의 표기를 유지할 것인지가 제일 어려웠다.
그래서 ChatGPT와 노력하던 중(처음에는 ChatGPT가 괴상한 함수 설정을 많이 알려줬는데, 아무리 생각해도 그 정도까지는 필요가 없어보였다.) "join"과 "list comprehension"이라는 개념에 대해 알게 되었다.
- JOIN 함수는 문자열에서 문자 사이에 특정한 문자를 입력할 수 있는 함수이다.
string = "abc"
print(".".join(string))
#a.b.c
이때 JOIN 안에 리스트가 있으면, 앞의 "" 에 있는 내용을 사이에 두고 리스트를 합쳐 문자열로 만들라는 의미이다.
- List comprehension은 짧고 간단하게 리스트를 형성할 수 있는 문법이다.
[표현식 for 변수 in 반복가능한객체 if 조건]
for in 반복문을 돌면서, 조건을 만족하는 경우 표현식을 list에 넣게 된다.
따라서 내가 작성한 코드인
masked = "".join([ch if ch == alphabet or masked[i] != "_" else "_" for i, ch in enumerate(answer)])
에서, join 안의 list comprehension은
answer 안에서 for문을 도는 i, ch에 대해
※ enumerate는 index 값과 실제 값을 동시에 반환할 수 있게 만드는 명령어이다. 따라서 enumerate(answer)에 대해 i는 index, ch는 실제 값(여기서는 answer의 알파벳)을 받게 된다.
"ch가 입력한 alphabet과 같거나, ______인 masked의 i번째가 _이 아니면 ch를 넣고, 아니면 _를 넣어라"는 의미이다.
따라서 answer='answer'에 대해 alphabet='a'이면,
join문 안의 list는 ['a', '_', '_', '_', '_', '_']이 되고, 이를 ""으로 join했으므로 결국 masked는 아래와 같은 형태가 된다.
masked = 'a_____'
이후 다른 알파벳을 넣어도, masked에서 _이 아닌 알파벳이 채워진 부분은 masked[i] != "_"라는 조건으로 인해 없어지지 않고 그대로 남아있게 된다.
퀘스트 3번은 정말 어려웠다. 특히 List comprehension이라는 개념에 대해 알게 되었고, join을 문자열이 아닌 리스트에도 적용할 수 있다는 것도 새롭게 공부하게 되었다. (물론 문자열을 다룰 때와 리스트를 다룰 때의 역할이 약간 달랐다.)
'TIL' 카테고리의 다른 글
| 251013_SQLD_데이터 모델링의 요소 (0) | 2025.10.13 |
|---|---|
| 251002_SQLD_데이터 모델링 (0) | 2025.10.02 |
| 250930_SQL_실무에 적용할 수 있는 SQL 기술 (0) | 2025.09.30 |
| 250929_SQL 데이터 연결하기 (0) | 2025.09.29 |
| 250926_SQL 데이터 가공하기 (0) | 2025.09.26 |