기타 지식

어떻게 무작위 추출을 할 것인가?

쓸데없이 일찍 깨서 써보는 쓸데없는 글

왜냐면 코딩을 하는 사람은 이미 알 내용이고

코딩을 하지 않는 사람은 의미가 없는 내용이라

말 글대로 읽을거리 라고 생각하고 그냥 슥 읽어보면 됨

 

아는 형이 업무에 쓸 코딩을 해보고 싶다고 해서

알려준다고 내가 낸 과제의 결과물을 보고 같이 생각해보자고

 

과제 내용은

7포커의 카드 나눠주는 것을 구현할 것

플레이어는 2명

누가 이겼는지 판단하진 않아도 됨

 

결과물은 아래와 같음.

 

1.png

randrange 때문에 스페이드A(0)가 나오지 않는 문제가 있지만,

어쨌든 대부분의 로직에서는 문제될게 없음

 

여기서 현실세계와 코딩세계의 차이점이 나오는데

현실세계에서는 카드를 먼저 섞고, 위에서부터 카드를 나눠준다.

하지만 코딩 세계에서는 보통 카드를 만들고, 이미 나간 카드면 폐기하고 새로 만든다.

 

이 과제를 할 때 처음 코딩을 한 형은 2가지 부분에서 막혔음.

1. 카드의 모양과 숫자를 지정하기

2. 중복된 카드가 나오는 것을 막기

 

1번은 꼼수로 하는 법을 알려줘서 저 모양인데

나중에 족보 맞추는 로직이 추가되면 더 일이 많아지기에 꼼수임.

하지만 그건 이 글에서 다루고자 하는 내용이 아니라서 건너뛸거임.

 

2번은 파이썬이 아주 입문용으로 좋은 이유임

보면 if rand in card 라는 로직으로 한방에 끝냈음

이를 통해서 "이미 나간 카드면 폐기한다." 를 컴퓨터에게 제대로 명령한거지

 

어차피 그 형은 코딩은 사무자동화에 쓸 도구를 익히는 방법이라

느려도 상관 없지만 기왕이면 빠른게 좋기 때문에...

(위의 코드가 스페이드A를 안뱉는 것도 수정하고)

이게 어느정도 시간이 걸리는지를 측정해보자

 

위 코드에서 동작시간은 2군데에서 먹음

하나는 랜덤 그 자체를 몇번 하는지임.

하나는 새로 뽑은 랜덤이 있는지 확인하는 절차임.

그 부분을 측정하게 해보면....

 

rand 16, seek 98
rand 15, seek 94
rand 15, seek 92
rand 15, seek 93
rand 16, seek 100

....
avg 116.9 16.2 100.7

100번 반복해보니 카드 14장을 뽑는데,

평균적으로 16번의 카드 생성, 카드가 있는지 확인하는데 100번의 연산이 걸림

뽑는 카드숫자에 따라 어느정도 시간이 걸리는 그려보면2.png

이처럼 숫자가 커질수록 카드를 뽑는 시간보다,

중복된 카드인지 확인하는데 걸리는 시간이 더 긺

35장의 카드를 뽑을때는 약 920번의 연산이 걸리는데,

이중에 카드를 뽑는데 걸리는 연산은 전체의 6%에 불과하고, 대부분은 중복 확인 시간임

52장을 다 줄세우는데는 보통 5700번의 연산이 걸리는데, 카드 뽑기에는 240번 밖에 안 씀

 

(코딩해본 개붕이들은 rand에 걸리는 시간은 예측하지 못해도 seek에 걸린 시간은 n^2쯤 될거라고 생각했을거임)

rand는 안농 수열일텐데 어떻게 표현하는지 모르겠네.

애당초 이름도 안농 수열이 아니라 다른 이름이 있을텐데.

 

위 결과를 보면 이렇게 물을 수 있다.

이게 최선인가요?

 

경우마다 다른데, 13장까지 뽑을 때는 이게 최선이 맞습니다.

14장부터는 다른 방법으로 뽑는게 최선입니다.

게다가 분기예측이라던지 다른데서 걸리는 시간도 생각해보면

최선이 달라지는 카드 장이 달라질 수 있음

 

 

    card = list(range(0,52))
    for i in range(total):
      rand = random.randrange(i,52);
      card[i], card[rand] = card[rand], card[i]

 

먼저 나올 수 있는 카드를 다 생성하고,

i번째에 뽑아야 할 카드를, i~max 번째 사이에서 고른다.

그리고 그 둘을 바꾸면, i번째에 있는 카드를 고른 것이다.

 

와! i번째 카드 뽑기는 반드시 1번의 연산으로 끝이 난다.

결과물을 보면 아래와 같이 나오는데,

각 출력이 몇번째 카드를 섞은게 아니라 몇 장의 카드를 섞었는지를 보여주는거임

1 shuffled (총 1장만 섞음) -> 초기화 -> 2 shuffled(총 2장만 섞음)

2.png

i장의 카드를 섞는다고 하면, i+1번째부터는 전체적으로 정렬된걸 유지하는데

i장의 카드가 섞여있는 것을 볼 수 있어

하지만 i+1번째 카드에 뭐가 있는지는 중요한게 아니니 건너뛰어도 돼

10 shuffled의 스페이스 3에 네모친건 3번째 카드를 뽑을 때 rand한 결과가 3이 나와서, 자기자신과 바꿨기 때문이야

지금 보니 1번째 카드를 뽑을때도 1이 나와서 스페이드 A 값을 유지했네.

그리고 2번째를 뽑을때, 클로버3과 스페이드2를 바꾸고, 4번째를 뽑을때 클로버 3(자리에 있는 스페이드2)과 스페이드 4를 바꾼 결과야

 

이 경우 n장을 뽑는데 드는 연산은 52(처음에 카드를 생성) + (1 (카드 뽑기) + 3(카드 2장 바꾸기) ) * n 이야

이 값을 보고 어떤 형태로 코딩을 하는게 성능에 좋은지 알아내야지

 

이때, 위 로직이 정말 카드를 같은 확률로 뽑는지 의심을 할 수 있어

그러면 그걸 수학으로 구하거나.....

혹은 컴퓨터를 통해 반복을 해서 각 위치에 어떤 카드가 몇번 오는지 집계한 다음 그 값이 비슷한지 확인한다

같은 짓이 가능해

 

이 문제는 간단하니까 수학적으로 구하는 것도 어렵지 않아.

근데 안풀리면 그냥 컴퓨터보고 반복시켜서 값이 맞는지 확인하는 짓을 하기도 해.

 

 

이처럼 코딩은 어떠한 문제에 대해서 여러 방법이 있을 것이고

어느 방법이 더 좋은지는 직접 계산해보거나, 시뮬레이션을 하거나 하는 수가 있어

아무튼 중요한건 대부분의 문제는 여러 방법이 있다는 점임.

 

 

글을 쓰다보니 떠오르는 일화가

예전에 소녀전선이란 겜을 할 때, 칩셋을 맞추는 계산기를 만든 애가 있거든

근데 걔가 칩셋이 업데이트가 되었는데, 하루에 16%의 경우의 수를 채굴하고 있다며 일주일 뒤에 결과가 나온다길래

'이상한데.. 타일링 문제니까 기껏해야 (타일 경우수)^(최대 타일수)인데 그렇게 오래 걸리나?' (당시 기억으로 1시간 컷)

하고 직접 코딩해보니까 계산시간은 3분이면 결과물 나오던데 걔는 대체 뭘 한건지 의문이었음.

6개의 댓글

2022.01.16

cards=[i for i in range(0,52)]

cards14 = random.sample(cards,14)

 

myPrint(cards14[0:7])

myPrint(cards14[7:14])

 

나같으면 이렇게 했을 것 같은데 뭐가 더 빠른지는 파이썬을 많이 안써봐서 모르겠군...

0
@아스펜

샘플이 내가 저기 적은 스왑 방식일거임

먼저 후보군을 요청하잖아

 

나도 내부구조를 모르니 그걸 나타낸거고..

 

m개 후보중 n개를 뽑는다

1. 카드를 먼저 뽑는다 : 후보를 다 나열하기에 너무 크거나 샘플 숫자가 작을때.

n + n^2 연산

2. 카드를 먼저 섞는다 : 뽑는 갯수가 후보 수에 베해 크다.

m + 3* n

 

로또는 36개중 6개를 뽑으니 seek비용이 로또 생성비용보다 쌈

이벤트 추첨처럼 m>>n 이지만 m이 이미 생성된 경우는 스왑이 빠르고, 쿼리로 갯수만 아는 경우면 그냥 추첨이 빠르고 그렇지

0
2022.01.16
@월급받으며개드립하기

옹 같은 방식이었구만

0

C, C++, 포트란(F77, F95), 매트랩을 다 써보고 가장 마지막에 파이썬을 접했는데 너무 편해서 눈물이 나더라.

그리고 파이썬 얘기 나온 김에 random 모듈에서 중복 없는 난수 추출/셔플링 해주는 함수들도 예시로 추가해 "줘".

0
2022.01.17

자 이제 입문용 책을 추천해줘

0
2022.01.20

걍 카드 객체 만들고 섞으면 되잖아

0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜
5244 [기타 지식] 최근 지각변동이 일어나는 국내 항공업계 (수정판) 14 K1A1 20 2 일 전
5243 [기타 지식] 도카이촌 방사능 누출사고 실제 영상 21 ASI 2 6 일 전
5242 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 지구 2부 21 Mtrap 8 6 일 전
5241 [기타 지식] 100년을 시간을 넘어서 유행한 칵테일, 사제락편 - 바텐더 개... 5 지나가는김개붕 1 9 일 전
5240 [기타 지식] 오이...좋아하세요? 오이 칵테일 아이리쉬 메이드편 - 바텐더... 3 지나가는김개붕 2 10 일 전
5239 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 지구 1부 31 Mtrap 13 10 일 전
5238 [기타 지식] 칵테일의 근본, 올드 패션드편 - 바텐더 개붕이의 술 이야기 15 지나가는김개붕 14 11 일 전
5237 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 인류 2부 22 Mtrap 14 10 일 전
5236 [기타 지식] 웹툰 나이트런의 세계관 및 설정 - 인류 1부 13 Mtrap 20 11 일 전
5235 [기타 지식] 서부 개척시대에 만들어진 칵테일, 카우보이 그리고 프레리 ... 3 지나가는김개붕 5 15 일 전
5234 [기타 지식] 모던 클래식의 현재를 제시한 칵테일편 - 바텐더 개붕이의 술... 4 지나가는김개붕 2 16 일 전
5233 [기타 지식] 브라질에서 이 칵테일을 다른 술로 만들면 불법이다, 카이피... 5 지나가는김개붕 1 18 일 전
5232 [기타 지식] 럼, 라임, 설탕 그리고 다이키리 편 - 바텐더 개붕이의 술 이... 2 지나가는김개붕 6 19 일 전
5231 [기타 지식] 1999년 도카이촌 방사능누출사고 대량 방사능 피폭 피해자들 ... 9 ASI 5 19 일 전
5230 [기타 지식] 진짜 레시피는 아무도 모르는 칵테일 싱가포르 슬링편 - 바텐... 3 지나가는김개붕 2 19 일 전
5229 [기타 지식] 통계로 보는 연애 상황에서 외모의 중요성 8 개드립에서가장긴... 11 22 일 전
5228 [기타 지식] 추울 수록 단맛이 유행한다, 위스콘신 스타일 올드 패션드편 ... 1 지나가는김개붕 8 23 일 전
5227 [기타 지식] '얼마나 걸릴까?'를 찾는데 걸린 시간은.. 1 동부전선이상무 5 23 일 전
5226 [기타 지식] '누구나 아는' 노래에 대한 이야기 9 동부전선이상무 20 28 일 전
5225 [기타 지식] 알코올 중독에 빠질 수 있는 칵테일, 브랜디 알렉산더편 - 바... 2 지나가는김개붕 5 2024.03.27