2011년 6월 1일 수요일

중복하지 않는 난수 발생 기법 Part 1–Array in C# and List in Python

네이버 등을 검색해보면 로또 번호 생성기 소스가 많이 돌아다닌다. 랜덤을 이용해 번호 6개를 생성하는데 너나 할 것 없이 난수 발생 후 앞서 추출한 난수 목록에서 중복하는지 여부를 살펴보고 있으면 무시하고 없으면 추가하는 형태로 프로그램을 작성한다.

이를 보고 있으면 마치, “1부터 n까지 연속하는 자연수의 합을 구하라” 혹은 “m부터 n까지 연속하는 자연수의 합을 구하라”라고 물으면 어김없이 for (int i = 1; i < n + 1; i++) { result += i; } 라는 식으로 프로그램을 작성하는 것과 같은 난감함을 느낀다. 또는 DB 시퀄 쿼리 작성 시, 레코드 마다 어떤 작업을 처리해야 할 때 아무 생각 없이 cursor를 휘갈겨 쓰는 것과도 같다. (http://oscarsjpark.blogspot.com/2011/05/sql-query.html)

앞으로 총 5개 포스트를 통해 C#과 Python으로 로또 번호 추출 프로그램을 다룰 것이다. 이와 같은 중복하지 않는 난수 발생 기법은 보드 게임(화투, 포커 등) 또는 통계 처리를 위한 표본 선정 등에 동일하게 적용 할 수 있다.

 

Contents
1. Array in C# and List in Python
2. random in C# and Python
3. Shuffling
4. Shuffling in Python
5. Lottery

 

1. Array in C# and List

C#에서 배열 선언은 기존 C계열 언어에서와 그 용법은 동일하거나 유사하다. 로또의 경우 1부터 45까지 연속된 자연수 모음이므로 다음과 같이 선언할 수 있다.

// C#

static int[] lottoDeck = {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, 31, 32, 33, 34, 35, 36, 37, 38, 39,
                                  40, 41, 42, 43, 44, 45};

static 키워드로 할당 했을 때와 하지 않았을 때 차이를 메모리 내 heap과 stack을 언급하며 설명 하는 것은 너무 멀리 나가니 이에 대해 궁금하다면 Effective C# 등과 같은 서적을 참고하면 된다.

파이썬 기본 데이터 타입은 Number, String 그리고 List만 제공한다. (물론 List를 prototype으로 삼아 Hash를 제공하고 있다. 또 indexing 되지 않는 set도 제공한다.) 파이썬의 List 용법은 LISP에서와 같으며, C# 또는 자바에선 ArrayList, List<> (generic) 등과 같다.

# Python

lottoDeck = [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, 31, 32, 33, 34, 35, 36, 37, 38, 39,
                   40, 41, 42, 43, 44, 45]

Python에는 range 함수가 있어 아래와 같은 코드도 가능하다.

# Python

lottoDeck = range(1, 46)

IDLE 인터프리터에서 range를 이용한 것을 아래 그림에서 볼 수 있다. 단 range(min, max) 함수 호출 시, min 파라메터는 포함관계이고, max 파라메터는 제외관계이다.

2011-05-31 오후 3-57-54

흥미로운 것은 실제 모든 값을 나열하여 리스트를 생성한 것과 range로 만들었을 때 아래 그림과 같이 차이가 나는데 이는 python이 생성한 list 객체가 실제 데이터를 가질 수도 있지만 생성 규칙(production rule)을 가질 수도 있기 때문이다. 이는 근래 각광받는 언어학자인 Steve Pinker가 그의 저서 단어와 규칙에서 밝힌 바와 같이 인간의 마음 사전과 동일하다. 즉 영어에서 boy 가 boys 가 되고, work 가 worked 가 되는 것과 같은 규칙에 의해 변하는 단어는 암기 하지 않는다. 하지만 child 가 children 으로, calclus 가 calculi 로, run 이 ran 과 같이 불규칙하게 변하는 단어만 마음 사전에 담아두면 된다. (불규칙 단어는 약 120 ~ 170 여 개가 된다고 한다. 사실 이들 불규칙 단어도 핑커의 연구 결과에 따르면 음성학적인 규칙을 따르지만…)

2011-05-31 오후 4-05-16

값 할당으로 만든 리스트와 달리 생성 규칙에 의해 만들어진 리스트는 값 요청 시에 해당 값을 되돌려 주게 되므로 리스트 내 요소(element) 값을 변경 할 수 없다.

2011-06-01 오전 4-36-03

Python에서 리스트 내 요소간 교환(swap)을 하고자 한다면 값 할당을 통해 리스트를 생성해야만 한다.

다음 포스트에선 난수 생성을 위한 random을 활용하는 방법에 대해 살펴보도록 한다.

댓글 없음:

댓글 쓰기