티스토리 뷰

지금까지 배운 내용을 복습하기 위한 퀴즈를 드리겠습니다. 직접 한 번 풀어보시고 나서 정답을 확인해주세요.

Quiz) 당신의 학교에서는 파이썬 코딩 대회를 주최합니다.
참석률을 높이기 위해 댓글 이벤트를 진행하기로 하였습니다.
댓글 작성자들 중에 추첨을 통해 1명은 치킨, 3명은 커피 쿠폰을 받게 됩니다.
추첨 프로그램을 작성하시오.

조건1 : 편의상 댓글은 20명이 작성하였고 아이디는 1~20이라고 가정
조건2 : 댓글 내용과 상관 없이 무작위로 추첨하되 중복은 불가
조건3 : random 모듈의 shuffle 과 sample 을 활용

(출력 예제)
 -- 당첨자 발표 --
치킨 당첨자 : 1
커피 당첨자 : [2, 3, 4]
 -- 축하합니다 --

 

퀴즈를 풀기 위해 random 모듈의 shuffle() 과 sample() 의 활용 방법에 대해 먼저 설명 드리겠습니다.

 

여러분은 컴퓨터나 스마트폰 등을 통해 음악을 들을 때 어떻게 하시나요? 재생목록에 듣고 싶은 음악을 추가하고 처음부터 순서대로 들으시나요? 아니면 셔플(섞기) 옵션을 통해 무작위로 들으시나요? 저는 주로 셔플 + 전체 반복 옵션을 이용합니다. 그러면 재생 목록에 있는 노래가 순서 없이 아무렇게나 흘러나오고, 재생목록의 노래가 모두 재생되면 또 다시 무작위로 노래가 재생되겠지요. 이와 비슷합니다. shuffle() 함수는 단어 뜻 그대로 섞어주는 역할을 하는 함수입니다. 이 함수를 이용하면 리스트 안의 데이터들을 무작위로 섞어주지요. 단, 리스트 자체를 섞기 때문에 shuffle() 함수 사용 후에는 사용 전과 비교하여 데이터 순서가 달라질 수 있다는 점 주의해주셔야 합니다.

 

sample() 은 리스트 내에서 원하는 갯수의 값을 뽑는 동작을 수행합니다. 앞에서 우리는 random 모듈을 이용하여 로또 번호를 뽑아보는 실습을 했었는데요. 아쉽게도 번호를 뽑는 각각의 동작은 독립사건이기 때문에 중복 번호에 대한 처리는 되지 않았습니다. 이를 위해서는 이전에 뽑은 번호를 어딘가 저장해두었다가 새로운 번호를 뽑을 때 지금까지 나오지 않은 번호가 나올 때까지 반복하는 작업을 해야하는데요. sample() 함수를 이용하면 이런 번거로움 없이 한 번에 원하는 갯수만큼의 번호를 중복 없이 뽑을 수가 있답니다.

 

다음 코드를 실습해보면서 동작을 익힌 다음 이 함수들을 활용하여 퀴즈를 풀어보세요. sample() 함수를 사용할 때는 2번째 값을 1~5 사이로 바꿔가면서 여러 번 실습해보면 동작을 더욱 쉽게 이해하실 수 있습니다.

from random import *
lst = [1,2,3,4,5]
print(lst) # 원본 리스트
shuffle(lst) # 리스트를 뒤섞기
print(lst) # 섞은 후 리스트
print(sample(lst, 1)) # 리스트 내에서 1개를 무작위로 뽑기

퀴즈 내에서는 아이디 값들을 가진 리스트를 shuffle() 함수를 이용해서 한 번 뒤섞고, sample() 함수를 이용해서 추첨을 하도록 만들어보세요.

 

▼ 해설 보기

더보기

우선은 random 모듈을 사용해야 하니 코드 가장 윗줄에 import 를 먼저 해줄게요.

from random import *

조건1 의 1~20 에 해당하는 아이디를 만들려면 이렇게 할 수 있습니다.

users = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 

일일이 적으려니 조금 많죠? 그래도 20개니까 그나마 적을만합니다. 그런데 만약 아이디가 100 개라면 어떨까요? 1,000 개라면요? 아마 아이디 리스트를 만드는 데만 정말 많은 시간을 허비해야 할 것입니다. 다행히 파이썬에서는 range() 라는 걸 이용할 수가 있답니다. 시작 값과 끝 값을 정해주면, 시작 값부터 끝 값 직전까지의 연속된 숫자를 반환해주는데요. 우리 퀴즈를 위해서는 이렇게 하면 됩니다.

users = range(1, 21) # 1 부터 21 직전까지의 연속된 숫자 모음

조건3 에서 shuffle() 을 활용하라고 했으니 이렇게 적어 볼까요?

shuffle(users)

users 리스트를 손수 만드신 경우라면 사용 가능하지만, range() 를 통해 만들게 되면 에러가 발생합니다. 왜냐하면 shuffle() 은 리스트에 대해서만 사용이 가능한데 range() 를 통해 만들어진 데이터는 리스트 형태가 아니거든요. 하지만 파이썬이니까 아주 손쉽게 형태를 변환할 수 있습니다. 별 거 아니죠?

users = range(1, 21)
users = list(users) # range 를 list 로 변환
shuffle(users)

 

자 이제 리스트를 섞었으니, 이번에는 추첨을 해 봅시다.

여러분은 어떻게 접근하셨나요? 저는 이렇게 생각해봤습니다. 20 명 중에 치킨 당첨자 1명에 커피 당첨자 3명이고 중복이 없어야 하니, 처음부터 4명을 뽑은 다음 그 중 1명은 치킨, 나머지 3명은 커피 당첨자로 하면 어떨까요?

 

sample() 을 이용하면 아주 간단하게 작성할 수 있답니다.

winners = sample(users, 4) # users 리스트에서 중복 없이 4명을 추첨

 

이제 winners 에서 첫 번째 아이디는 치킨, 나머지는 커피 당첨자로만 해주면 되겠네요. 슬라이싱을 이용하면 이 동작도 쉽게 해결 가능합니다.  

print(" -- 당첨자 발표 -- ")
print("치킨 당첨자 : {0}".format(winners[0])) # 0 번째 인덱스 (1명)
print("커피 당첨자 : {0}".format(winners[1:])) # 1 번째부터 마지막까지 슬라이싱 (3명)
print(" -- 축하합니다 --")

 

전체 코드는 이렇습니다.

from random import *

users = range(1, 21)
users = list(users)
shuffle(users)

winners = sample(users, 4)

print(" -- 당첨자 발표 -- ")
print("치킨 당첨자 : {0}".format(winners[0]))
print("커피 당첨자 : {0}".format(winners[1:]))
print(" -- 축하합니다 --")

 

 

다소 황당하지요?

아마 많은 분들이 이렇게 접근하셨을 것 같아요.

 

"20명 중에서 1명을 먼저 뽑고, 이 사람을 제외한 19명 중에서 3명을 뽑아야겠다. 그런데 제외를 어떻게 하지?"

네, 아주 좋은 방법입니다. 절대 잘못된 접근이 아니에요. 그러면 이런 방식으로도 한 번 풀어볼까요?

 

일단 여기까지는 크게 다르지 않구요.

from random import *

users = list(range(1, 21)) # range 를 list 로 바로 감싸면 한 줄 더 줄일 수 있어요!
shuffle(users)

 

치킨 당첨자를 먼저 1명 뽑아서 변수에 저장해봅시다.

chicken_winner = sample(users, 1) # 치킨 당첨자 1명 추첨

 

이제는 전체 리스트 중에서 치킨 당첨자를 제외시켜야겠죠? 그러기 위해서 어떻게 하는 게 좋을까요?

 

맞습니다! 차집합.

우리는 set 자료구조를 이용하여 쉽게 차집합을 적용할 수 있습니다.

remain_users = set(users) - set(chicken_winner) # 전체 집합에서 치킨 당첨자 집합을 제외

그러면 남은 부분은 크게 다르지 않겠네요. remain_users 에 19명만 남아 있을테니 이 중에서 커피 당첨자 3명을 뽑으면 되겠죠?

coffee_winners = sample(remain_users, 3) # 남은 19명 중에서 3명 추첨

이제 끝났습니다. 치킨 당첨자와 커피 당첨자가 뽑혔으니 그대로 출력만 해주면 되겠네요.

print("-- 당첨자 발표 --")
print("치킨 당첨자 : {0}".format(chicken_winner))
print("커피 당첨자 : {0}".format(coffee_winners))
print("-- 축하합니다 --")

 

전체 코드입니다.

from random import *

users = list(range(1, 21)) # range 를 list 로 바로 감싸면 한 줄 더 줄일 수 있어요!
shuffle(users)

chicken_winner = sample(users, 1) # 치킨 당첨자 1명 추첨
remain_users = set(users) - set(chicken_winner) # 전체 집합에서 치킨 당첨자 집합을 제외
coffee_winners = sample(remain_users, 3) # 남은 19명 중에서 3명 추첨

print("-- 당첨자 발표 --")
print("치킨 당첨자 : {0}".format(chicken_winner))
print("커피 당첨자 : {0}".format(coffee_winners))
print("-- 축하합니다 --")

 

이렇게 해서 2가지 방법으로 퀴즈 풀이를 해 봤습니다. 문제 해결을 위한 적절한 방법을 찾아내는 것도 무척 중요하지만, 때로는 유연한 사고를 통해서 보다 쉬운 접근 방법을 고민해보는 것도 중요하답니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함