みけCATのにっき(仮)
つれづれなるまゝに、日くらし、PCにむかひて、心に移りゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
(本当か!?)
出典

一度出た数字を出さない乱数

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

一度出た数字を出さない乱数

投稿記事 by みけCAT » 13年前

一度出た数字を出さない乱数を取得するクラスです。
まず、残っている数字の中で何番目の数を返すかを乱数で決め、
それがいくつなのかを二分探索により決定して返します。

CODE:

#include 
#include 
#include 

class UniqueRand {
	private:
		static const int BIT_MAX=10;
		int bitTable[BIT_MAX];

		void bitInit();
		void bitAdd(int pos,int value);
		int bitSum(int pos);

	public:
		void init();
		void registerNumber(int num);
		void unRegisterNumber(int num);
		int nextInt();
		UniqueRand(){init();}
};

void UniqueRand::bitInit() {
	for(int i=0;i0) {
		sum+=bitTable[pos-1];
		pos-=pos & (-pos);
	}
	return sum;
}

void UniqueRand::init() {
	bitInit();
}

void UniqueRand::registerNumber(int num) {
	if(num=BIT_MAX)return;
	if(bitSum(num)-(num==0?0:bitSum(num-1))!=0)return;
	bitAdd(num,1);
}

void UniqueRand::unRegisterNumber(int num) {
	if(num=BIT_MAX)return;
	if(bitSum(num)-(num==0?0:bitSum(num-1))==0)return;
	bitAdd(num,-1);
}

int UniqueRand::nextInt() {
	int left,right,mid;
	int max=BIT_MAX-bitSum(BIT_MAX-1);
	if(max=pos)right=mid-1; else left=mid+1;
	}
	registerNumber(right+1);
	return right+1;
}

int main(void) {
	int query;
	UniqueRand urn;
	srand((unsigned int)time(NULL));

	while(putchar('>'),(scanf("%d",&query)==1)) {
		if(query==0) {
			int theNumber=urn.nextInt();
			if(theNumber>=0) {
				printf("Got number %d\n",theNumber+1);
			} else {
				printf("There is no numbers left.\n");
			}
		} else if(query>0) {
			urn.unRegisterNumber(query-1);
			printf("Unregistered %d\n",query);
		} else break;
	}
	return 0;
}
void init() : 数が出たフラグを初期化します。
void registerNumber(int num) : numの出たフラグを立て、乱数で出ないようにします。
void unRegisterNumber(int num) : numの出たフラグを折り、乱数で出るようにします。
int nextInt() : 次の乱数を取得します。

このサンプルプログラムでは、
0を入力すると次の乱数(1~10)を取得し、
正の整数を入力するとその整数の出たフラグを折ります。
負の整数を入力すると終了します。

コメントはまだありません。