まず、残っている数字の中で何番目の数を返すかを乱数で決め、
それがいくつなのかを二分探索により決定して返します。
#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 registerNumber(int num) : numの出たフラグを立て、乱数で出ないようにします。
void unRegisterNumber(int num) : numの出たフラグを折り、乱数で出るようにします。
int nextInt() : 次の乱数を取得します。
このサンプルプログラムでは、
0を入力すると次の乱数(1~10)を取得し、
正の整数を入力するとその整数の出たフラグを折ります。
負の整数を入力すると終了します。