지금까지 배운 내용으로 조편성 코드를 만들어 볼 것이다.

  • 매개변수: 총 인원수, 조원 수
  • random을 사용하여 무작위로 배정
  • 'list'자료형과 'dictionary' 자료형을 사용

로또 추첨상자를 생각한다고 코드를 짠 후 치환하니 편했다.


이제 이렇게 가정하고 코드를 작성한다

  • 매개변수: 로또 추첨 공의 개수, 모든 추첨 공의 개수
  • random을 사용하여 무작위 개수의 로또 공을 추첨
  1. 매개변수로 받은 모든 추첨 공의 개수를 의미하는 list를 하나 만든다.
로또 추첨 상자 = list(range(1, 45+1)
  1. 이 list에서 random.sample(리스트, 개수)메서드를 사용하여 임의의 요소를 추출한다. 메서드 결과물의 반환형 또한 리스트이다.
당첨된 공 = random.sample(로또 상자, 6)
# ex print(추첨된 공)
	>> [1, 7, 41, 42, 31, 19]
  1. 이 당첨된 공 세트(list)를 '당첨 번호 모음' 세트에 추가하는 것이다. list에 요소를 추가하는 것이므로 append()를 사용하면 된다.
로또 당첨 숫자 세트 = []
로또 당첨 숫자 세트.append(당첨된 공 세트)
  1. 뽑은 공이 상자에 남아 있으면 안 되므로 없애준다.
if 당첨된 공 in 로또 상자:
	로또상자.remove(당첨된 공)

remove(값)메서드는 value기준으로 list의 요소를 삭제해주기 때문에 편리하게 사용할 수 있다.

  1. 이를 반복하면 여러 세트의 '당첨된 공 세트'가 '로또 당첨 숫자 세트'에 들어갈 것이다.

여기까지를 코드로 옮기면

import random

# 로또 당첨 숫자 세트
cls = []

# 총 공의 개수는?
total = list(range(1, 45+1))

# 당첨 숫자 조합은 몇 개?
group = 25//4

# 공을 뽑기 시작하는데
for _ in range(1, group+1):
	# 상자에 적어도 6개는 남아 있어야 추첨이 가능하다
    if len(total) >= 6:
    	# 로또 상자에서 6개의 요소를 임의로 꺼내 '당첨된 공 세트'로 만든다
        picker = random.sample(total, 6)
        # 로또 당첨 숫자 세트에 넣는다
        cls.append(picker)
		
        # 뽑은 공은 상자에선 사라져야 한다
		for val in picker:
        	# 뽑은 공을 상자에서 확인하고
            if val in total:
            	# 삭제한다
                total.remove(val)
    # 초기 조건인 공의 개수가 6개가 아니라면
    else:
    	# 반복문을 종료한다
        break

print(cls.a)
[
	[1, 8, 9, 17, 18, 25, 34],
    [2, 5, 3, 44, 41, 31, 37],
    ....
]

이런 식으로 나올 것이다.
로또 당첨 숫자를 중복없이 뽑는 방법은 여기서 끝.


이제 다시 조 편성으로 돌아오겠다.
'로또 당첨 숫자 세트'는 '반'이 된다.
'당첨된 공 세트'는 '조'가 된다.

로또와 달리, 조 편성에서 남는 인원이 있다면 이미 편성된 조에 적절히 나눠줘야 한다.

  1. 조 편성 인원보다 남은 인원이 적은 경우, 남은 인원 중 임의의 1명을 뽑는다.

  2. 이미 편성된 조에서도 임의의 조를 하나 뽑는다.

  3. 임의로 선택된 조에 임의로 선택된 남은 인원을 붙인다.

  4. 남은 인원은 전체 인원 리스트에서 삭제해준다.

  5. 반복한다.

  6. 남은 인원이 없을 때 반복을 종료한다.

...
while True:
	# 남은 인원이 조 편성 인원보다 적을 때
    if 0 < len(total) < num_member:
    	# 남은 인원 중 무작위 한 명을 뽑는다
        picker = random.sample(total, 1)
        # 이미 편성된 조들 중에 하나의 조를 무작위로 뽑는다
        group_picker = random.sample(cls, 1)
		
        # 남은 인원이 들어갈 조에 직접 접근하기 위해 인덱스를 알아낸다
        group_index = cls.index(group_picker_last)
        # 인덱스를 통해 본 값에 접근하여 남은 인원을 집어 넣는다
        cls[group_index].append(picker[0])
        # 조에 들어간 인원은 총원에서 삭제한다
        total.remove(picker[0])
	# 남은 인원이 0명이 되면 
    if len(total) == 0:
        # 반복을 종료한다
        break

이렇게 하면 끝이 난다.
만약 이 코드로 총원 25명을 4명씩 한 조로 만든다면

[
	[8, 1, 9, 14], 
    [10, 13, 6, 15], 
    [17, 3, 2, 23], 
    [18, 21, 16, 20], 
    [5, 24, 7, 19, 12], 
    [11, 4, 22, 25]
]

이렇게 번호로된 조 편성 값을 볼 수 있다.
이 번호를 딕셔너리를 통해 매핑할 수도 있다.

    name_tag = {
            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:'지눌'
            }

코드의 앞부분에 미리 딕셔너리를 정의한다.

                ### mapping ###
    # 매핑을 하면서 새로운 반을 만들 것이다
    r_cls = []
    # 조를 하나하나 불러오면서
    for r_group in cls:
    	# 번호를 이름으로 바꿔 새롭게 만들 준비를 한다
        map_group = []
        # 인덱스를 따라 요소를 조회하고
        for index in range(len(r_group)):
            # 요소를 딕셔너리의 값으로 매핑한다           
            map_group.append(name_tag[r_group[index]])
        r_cls.append(map_group)
                ### end of mapping 

이렇게 하면 매핑된 이름으로 조를 볼 수 있다.

[
   ['허준', '내물마립간', '박경종', '최승로', '신립'],
   ['정조', '이승만', '이산', '원효', '광개토'],
   ['효녀지은', '이하응', '홍길동', '김유신', '장금'],
   ['정몽주', '고이왕', '이순신', '윤관', '이성계'],
   ['지눌', '왕건', '강감찬', '박혁거세', '정지상']
 ]

이렇게 역사상 유래 없는 드림팀을 임의로 짜볼 수도 있다.

전체 코드를 함수로 묶어서 작성하면 다음과 같다.

def group_selector(total, num_member):
   import random
   
   name_tag = {
           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:'지눌'
           }

   cls = []
   group = total//num_member
   
   if group < 2:
       return "조를 나눌 수 없습니다"
   
   total = list(range(1, total+1))


   for _ in range(1, group+1):
       if len(total) >= num_member:
           picker = random.sample(total, num_member)
           cls.append(picker)

           for val in picker:
               if val in total:
                   total.remove(val)
       else:
           break       

   while True:
       if 0 < len(total) < num_member:
           picker = random.sample(total, 1)
           group_picker = random.sample(cls, 1)

           group_index = cls.index(group_picker)
           cls[group_index].append(picker[0])
           total.remove(picker[0])

       if len(total) == 0:
           break
           
               ### mapping ###
   r_cls = []
   for r_group in cls:
       map_group = []
       for index in range(len(r_group)):
           map_group.append(name_tag[r_group[index]])
       r_cls.append(map_group)
               ### end of mapping 
       
   return r_cls

만약 인원이 많아져서 x조의 인원만 확인하고 싶다면 이렇게 해볼 수 있겠다.

def group_reader(cls, number):
   index = number
   data = cls
   return f"{index}조:",data[index]

앞서 작성했던 함수의 리턴값을 cls라는 변수로 받고, number에는 몇 조인지(1조, 2조...) 번호를 입력한다.
이를 실행하면 원하는 번호의 조원들을 조회할 수 있다.

a = group_selector(25, 5)
group_reader(a, 1)
>>
('1조:', ['이하응', '박혁거세', '이승만', '강감찬', '내물마립간'])

이렇게 함수의 리턴값을 이용하여 여러가지 접근이 가능하고, 여러 가지 보조 함수들을 만들어 사용할 수 있다.

재밌다!

0개의 댓글