Turbo-C
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
터보-C 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
Lua 게시판
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C/C++ 팁&트릭
[6] [STL]generator와 random_shuffle 알고리듬에 사용할 난수 생성기 구현
김백일 [cedar] 7084 읽음    2002-05-09 02:18
특정 컨테이너를 1, 2, ... , 10 으로 채우려면 어떻게 해야 할까요?
제일 쉬운 방법은 이전 글(5번)에서 설명한
iota 알고리듬을 사용하는 방법입니다.

vector<int> v1(10);
iota(v1.begin(), v1.end(), 1);

generate를 사용하려면 어떻게 해야 할까요?
다음과 같은 함수 객체를 만들면 됩니다.

3번 글에서 Cin 함수 객체를 만들었던 것과 유사하나,
생성자에 시작 값(start)을 지정하는 파라미터를 추가하였습니다.

class IntSeq {
public:
   IntSeq(int start = 0) : current(start) { }
   int operator()() { return current++; }
private:
   int current;
};

....

generate(v1.begin(), v1.end(), IntSeq(1));

그럼 이번에는 0~99까지의 임의의 난수로 채우려면 어떻게 해야 할까요?
역시 iotaGen과 비슷합니다.
생성자에 범위(range)를 지정하는 파라미터를 사용합니다.

class RandomGenerator {
public:
    RandomGenerator(int r) : range(r) { randomize(); } // 난수 생성기를 초기화합니다.
    int operator() () { return random(range); } // 파라미터가 없습니다.
private:
    int range;
};

// randomize()와 random()은 볼랜드 C에만 있습니다.
// 다른 컴파일러 사용자는 적당히 알아서(?) 구현하세요.

generate(v1.begin(), v1.end(), RandomGenerator(100));

자, 이번에는 화제를 돌려서
random_shuffle 알고리듬을 알아봅시다.

template <class RandomAccessIterator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last);

template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
                    RandomNumberGenerator& rand)

이 알고리듬은 [first, last)까지의 시퀀스를 임의로 뒤섞는 기능을 합니다.
그런데 여기서, 별도의 RandomNumberGenerator를 사용하지 않은 첫번째 알고리듬에는
한가지 문제점이 있습니다.
프로그램을 실행할 때마다 똑같은 결과가 나온다는 거지요.
즉, random_shuffle 자체가 사용하는 난수 생성기는 (예를 들어 randomize()를 써서)
실행할 때마다 난수를 초기화시키는 기능이 없다는 얘기입니다.
결국 난수를 초기화 기능을 사용하려면
별도의 사용자 정의 RandomNumberGenerator를 사용해야 합니다.

그런데, 이 RandomNumberGenerator는 앞에서 generate에 사용한 함수 객체와는
다른 방법으로 정의해야 합니다.
즉, 앞에서 사용된 함수 객체는 객체 생성자에는 파라미터를 사용할 수 있지만,
함수 호출시에는 파라미터가 없습니다. 이러한 함수 객체를 Generator라고 합니다.
그러나 random_shuffle에서 사용하는 함수 객체는 파라미터 1개가 반드시 필요합니다.
이러한 함수 객체를 Unary Function이라고 합니다.
만약 파라미터가 두개가 필요한 경우는 Binary Function이라고 합니다.

여기서 정의할 함수 객체를 RandomFunction이라고 하겠습니다.
이 경우는 생성자에 파라미터가 필요없고, 멤버 변수도 필요없기 때문에
훨씬 간단하게 정의할 수 있습니다.

// Example for random_shuffle()
#include<cstdlib>
#include<iostream>
#pragma hdrstop
#include<vector>
#include<iterator>
#include<algorithm>
#include<numeric>

using namespace std;

struct RandomFunction {
    RandomFunction() { randomize(); }
    int operator() (int X) { return random(X); }
};

int main() {
    vector<int> v(12);
    iota(v.begin(), v.end(), 0);            // 0 1 2 3 4 5 6 7 8 9 10 11
    ostream_iterator<int> out(cout, " ");
    copy(v.begin(), v.end(), out);
    cout << endl;

    random_shuffle(v.begin(), v.end());     // 1 5 11 2 6 4 10 8 7 0 9 3 (빌더 6 STLport의 경우)
    copy(v.begin(), v.end(), out);
    cout << endl;

    random_shuffle(v.begin(), v.end(), RandomFunction());  // 매번 실행 시마다 다르다.
    copy(v.begin(), v.end(), out);
    cout << endl;

    return 0;
}

+ -

관련 글 리스트
6 [STL]generator와 random_shuffle 알고리듬에 사용할 난수 생성기 구현 김백일 7084 2002/05/09
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.